Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / plasma / dataengines / weather / ions / ion_bbcukmet.cpp
blob6b8cc92d54c3a74b15d0be7c9bc3406b984ace3d
1 /***************************************************************************
2 * Copyright (C) 2007 by Shawn Starr <shawn.starr@rogers.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
18 ***************************************************************************/
20 /* Ion for BBC's Weather from the UK Met Office */
22 #include "ion_bbcukmet.h"
24 class UKMETIon::Private : public QObject
26 public:
27 Private() {}
28 ~Private() {}
30 private:
31 struct XMLMapInfo {
32 QString place;
33 QString XMLurl;
34 QString XMLforecastURL;
35 bool ukPlace;
36 QString sourceOptions;
39 public:
40 // Key dicts
41 QHash<QString, UKMETIon::Private::XMLMapInfo> m_place;
42 QVector<QString> m_locations;
43 QStringList m_matchLocations;
44 bool isValid;
46 public:
47 // Weather information
48 QHash<QString, WeatherData> m_weatherData;
50 // Store KIO jobs - Search list
51 QMap<KJob *, QXmlStreamReader*> m_jobXml;
52 QMap<KJob *, QString> m_jobList;
54 QMap<KJob *, QXmlStreamReader*> m_obsJobXml;
55 QMap<KJob *, QString> m_obsJobList;
57 QMap<KJob *, QXmlStreamReader *> m_forecastJobXml;
58 QMap<KJob *, QString> m_forecastJobList;
60 KUrl *m_url;
61 KIO::TransferJob *m_job;
63 int m_timezoneType; // Ion option: Timezone may be local time or UTC time
64 int m_measureType; // Ion option: Units may be Metric or Imperial
68 // ctor, dtor
69 UKMETIon::UKMETIon(QObject *parent, const QVariantList &args)
70 : IonInterface(parent), d(new Private())
73 Q_UNUSED(args)
76 UKMETIon::~UKMETIon()
78 // Destroy each forecast stored in a QVector
79 foreach(WeatherData item, d->m_weatherData) {
80 foreach(WeatherData::ForecastInfo *forecast, item.forecasts) {
81 if (forecast) {
82 delete forecast;
87 // Destroy dptr
88 delete d;
91 // Get the master list of locations to be parsed
92 void UKMETIon::init()
94 setInitialized(true);
97 // Get a specific Ion's data
98 bool UKMETIon::updateIonSource(const QString& source)
100 // We expect the applet to send the source in the following tokenization:
101 // ionname|validate|place_name - Triggers validation of place
102 // ionname|weather|place_name - Triggers receiving weather of place
104 QStringList sourceAction = source.split('|');
106 if (sourceAction[1] == QString("validate")) {
107 // Look for places to match
108 findPlace(sourceAction[2], source);
109 return true;
111 } else if (sourceAction[1] == QString("weather")) {
112 if (sourceAction.count() >= 3) {
113 d->m_place[QString("bbcukmet|%1").arg(sourceAction[2])].XMLurl = sourceAction[3];
114 getXMLData(QString("%1|%2").arg(sourceAction[0]).arg(sourceAction[2]));
115 return true;
116 } else {
117 return false;
120 return false;
123 // Gets specific city XML data
124 void UKMETIon::getXMLData(const QString& source)
126 KUrl url;
127 url = d->m_place[source].XMLurl;
129 d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
130 d->m_job->addMetaData("cookies", "none"); // Disable displaying cookies
131 d->m_obsJobXml.insert(d->m_job, new QXmlStreamReader);
132 d->m_obsJobList.insert(d->m_job, source);
134 if (d->m_job) {
135 connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
136 SLOT(observation_slotDataArrived(KIO::Job *, const QByteArray &)));
137 connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(observation_slotJobFinished(KJob *)));
141 // Parses city list and gets the correct city based on ID number
142 void UKMETIon::findPlace(const QString& place, const QString& source)
144 KUrl url;
145 url = "http://www.bbc.co.uk/cgi-perl/weather/search/new_search.pl?x=0&y=0&=Submit&search_query=" + place + "&tmpl=wap";
147 d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
148 d->m_job->addMetaData("cookies", "none"); // Disable displaying cookies
149 d->m_jobXml.insert(d->m_job, new QXmlStreamReader);
150 d->m_jobList.insert(d->m_job, source);
152 if (d->m_job) {
153 connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
154 SLOT(setup_slotDataArrived(KIO::Job *, const QByteArray &)));
155 connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(setup_slotJobFinished(KJob *)));
157 // Handle redirects for direct hit places.
158 connect(d->m_job, SIGNAL(redirection(KIO::Job *, const KUrl &)), this,
159 SLOT(setup_slotRedirected(KIO::Job *, const KUrl &)));
163 void UKMETIon::getFiveDayForecast(const QString& source)
165 KUrl url;
166 url = d->m_place[source].XMLforecastURL.replace("weather/5day.shtml", "weather/mobile/5day.wml");
168 d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
169 d->m_job->addMetaData("cookies", "none"); // Disable displaying cookies
170 d->m_forecastJobXml.insert(d->m_job, new QXmlStreamReader);
171 d->m_forecastJobList.insert(d->m_job, source);
173 if (d->m_job) {
174 connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
175 SLOT(forecast_slotDataArrived(KIO::Job *, const QByteArray &)));
176 connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(forecast_slotJobFinished(KJob *)));
180 bool UKMETIon::readSearchXMLData(const QString& key, QXmlStreamReader& xml)
183 while (!xml.atEnd()) {
184 xml.readNext();
186 if (xml.isEndElement()) {
187 break;
190 if (xml.isStartElement()) {
191 if (xml.name() == "wml") {
192 parseSearchLocations(key, xml);
193 } else {
194 parseUnknownElement(xml);
199 return !xml.error();
202 void UKMETIon::parseSearchLocations(const QString& source, QXmlStreamReader& xml)
204 int flag = 0;
205 QString url;
206 QString place;
207 QStringList tokens;
208 QString tmp;
209 int counter = 2;
210 int currentParagraph = 0;
212 Q_ASSERT(xml.isStartElement() && xml.name() == "wml");
214 while (!xml.atEnd()) {
215 xml.readNext();
217 if (xml.isEndElement() && xml.name() == "wml") {
218 break;
221 if (xml.isStartElement() && xml.name() == "p") {
222 currentParagraph++;
225 if (currentParagraph == 2) {
226 if (xml.isCharacters() && !xml.isWhitespace()) {
227 QString dataText = xml.text().toString().trimmed();
228 if (dataText.contains("No locations")) {
229 break;
234 if (xml.isStartElement()) {
235 if (xml.name() == "a" && !xml.attributes().value("href").isEmpty()) {
236 if (xml.attributes().value("href").toString().contains("5day.wml")) {
238 // Split URL to determine station ID number
239 tokens = xml.attributes().value("href").toString().split("=");
240 if (xml.attributes().value("href").toString().contains("world")) {
241 url = "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens[1] + ".xml";
242 flag = 0;
243 } else {
244 url = "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens[1] + ".xml";
245 flag = 1;
247 place = xml.readElementText();
248 tmp = QString("bbcukmet|%1").arg(place);
250 // Duplicate places can exist
251 if (d->m_locations.contains(tmp)) {
253 QString dupePlace = place;
254 tmp = QString("bbcukmet|%1").arg(QString("%1 (#%2)").arg(dupePlace).arg(counter));
255 place = QString("%1 (#%2)").arg(dupePlace).arg(counter);
256 counter++;
259 if (flag) { // This is a UK specific location
260 d->m_place[tmp].XMLurl = url;
261 d->m_place[tmp].place = place;
262 d->m_place[tmp].ukPlace = true;
263 } else {
264 d->m_place[tmp].XMLurl = url;
265 d->m_place[tmp].place = place;
266 d->m_place[tmp].ukPlace = false;
268 d->m_locations.append(tmp);
273 validate(source);
276 // handle when no XML tag is found
277 void UKMETIon::parseUnknownElement(QXmlStreamReader& xml)
279 while (!xml.atEnd()) {
280 xml.readNext();
282 if (xml.isEndElement()) {
283 break;
286 if (xml.isStartElement()) {
287 parseUnknownElement(xml);
292 void UKMETIon::setup_slotRedirected(KIO::Job *job, const KUrl &url)
294 QString obsUrl;
295 QString place;
296 QString tmp;
297 bool flag = false;
298 QStringList tokens = url.url().split("=");
299 if (url.url().contains("xhtml")) { // We dont care about the first redirection (there is two)
300 if (url.url().contains("world")) {
301 obsUrl = "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens[2] + ".xml";
302 flag = false;
303 } else {
304 obsUrl = "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens[2] + ".xml";
305 flag = true;
307 place = d->m_jobList[job].split("|")[2]; // Contains the source name (place in this case)
308 tmp = QString("bbcukmet|%1").arg(place);
309 place[0] = place[0].toUpper();
311 if (flag) { // This is a UK specific location
312 d->m_place[tmp].XMLurl = obsUrl;
313 d->m_place[tmp].place = place;
314 d->m_place[tmp].ukPlace = true;
315 } else {
316 d->m_place[tmp].XMLurl = obsUrl;
317 d->m_place[tmp].place = place;
318 d->m_place[tmp].ukPlace = false;
320 d->m_locations.append(tmp);
321 validate(d->m_jobList[job]);
325 void UKMETIon::setup_slotDataArrived(KIO::Job *job, const QByteArray &data)
327 QByteArray local = data;
328 if (data.isEmpty() || !d->m_jobXml.contains(job)) {
329 return;
332 // XXX: BBC doesn't convert unicode strings so this breaks XML formatting. Not pretty.
333 if (local.startsWith("<?xml version")) {
334 local.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
337 // Send to xml.
338 d->m_jobXml[job]->addData(local);
341 void UKMETIon::setup_slotJobFinished(KJob *job)
343 if (job->error() == 149) {
344 setData(d->m_jobList[job], "validate", QString("bbcukmet|timeout"));
345 disconnectSource(d->m_jobList[job], this);
346 d->m_jobList.remove(job);
347 delete d->m_jobXml[job];
348 d->m_jobXml.remove(job);
349 return;
351 // If Redirected, dont go to this routine
352 if (!d->m_locations.contains(QString("bbcukmet|%1").arg(d->m_jobList[job]))) {
353 readSearchXMLData(d->m_jobList[job], *d->m_jobXml[job]);
355 d->m_jobList.remove(job);
356 delete d->m_jobXml[job];
357 d->m_jobXml.remove(job);
360 void UKMETIon::observation_slotDataArrived(KIO::Job *job, const QByteArray &data)
362 QByteArray local = data;
363 if (data.isEmpty() || !d->m_obsJobXml.contains(job)) {
364 return;
367 // XXX: I don't know what to say about this. But horrible. We can't really do much about this :/
368 // No, it's not UTF-8, it really lies.
369 if (local.startsWith("<?xml version")) {
370 local.replace("encoding=\"UTF-8\"?>", "encoding=\"cp1252\" ?>");
373 // Send to xml.
374 d->m_obsJobXml[job]->addData(local);
377 void UKMETIon::observation_slotJobFinished(KJob *job)
379 readObservationXMLData(d->m_obsJobList[job], *d->m_obsJobXml[job]);
380 d->m_obsJobList.remove(job);
381 delete d->m_obsJobXml[job];
382 d->m_obsJobXml.remove(job);
385 void UKMETIon::forecast_slotDataArrived(KIO::Job *job, const QByteArray &data)
387 QByteArray local = data;
388 if (data.isEmpty() || !d->m_forecastJobXml.contains(job)) {
389 return;
392 // XXX: BBC doesn't convert unicode strings so this breaks XML formatting. Not pretty.
393 // No, it's not UTF-8, it really lies.
394 if (local.startsWith("<?xml version")) {
395 local.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
397 // Send to xml.
398 d->m_forecastJobXml[job]->addData(local);
401 void UKMETIon::forecast_slotJobFinished(KJob *job)
403 readFiveDayForecastXMLData(d->m_forecastJobList[job], *d->m_forecastJobXml[job]);
404 d->m_forecastJobList.remove(job);
405 delete d->m_forecastJobXml[job];
406 d->m_forecastJobXml.remove(job);
409 void UKMETIon::parsePlaceObservation(const QString &source, WeatherData& data, QXmlStreamReader& xml)
411 Q_ASSERT(xml.isStartElement() && xml.name() == "rss");
413 while (!xml.atEnd()) {
414 xml.readNext();
416 if (xml.isEndElement() && xml.name() == "rss") {
417 break;
420 if (xml.isStartElement()) {
421 if (xml.name() == "channel") {
422 parseWeatherChannel(source, data, xml);
428 void UKMETIon::parseWeatherChannel(const QString& source, WeatherData& data, QXmlStreamReader& xml)
430 Q_ASSERT(xml.isStartElement() && xml.name() == "channel");
432 while (!xml.atEnd()) {
433 xml.readNext();
435 if (xml.isEndElement() && xml.name() == "channel") {
436 break;
439 if (xml.isStartElement()) {
440 if (xml.name() == "title") {
441 data.stationName = xml.readElementText().split("Observations for")[1].trimmed();
442 } else if (xml.name() == "item") {
443 parseWeatherObservation(source, data, xml);
444 } else {
445 parseUnknownElement(xml);
451 void UKMETIon::parseWeatherObservation(const QString& source, WeatherData& data, QXmlStreamReader& xml)
453 Q_UNUSED(data)
454 Q_ASSERT(xml.isStartElement() && xml.name() == "item");
456 while (!xml.atEnd()) {
457 xml.readNext();
459 if (xml.isEndElement() && xml.name() == "item") {
460 break;
463 if (xml.isStartElement()) {
464 if (xml.name() == "title") {
465 QString conditionString = xml.readElementText();
467 // Get the observation time.
468 QStringList conditionData = conditionString.split(":");
470 data.obsTime = conditionData[0];
471 data.condition = conditionData[1].split(".")[0].trimmed();
472 } else if (xml.name() == "link") {
473 d->m_place[source].XMLforecastURL = xml.readElementText();
474 } else if (xml.name() == "description") {
475 QString observeString = xml.readElementText();
476 QStringList observeData = observeString.split(":");
478 data.temperature_C = observeData[1].split(QChar(176))[0].trimmed();
479 data.temperature_F = observeData[1].split("(")[1].split(QChar(176))[0];
481 data.windDirection = observeData[2].split(",")[0].trimmed();
482 data.windSpeed_miles = observeData[3].split(",")[0].split(" ")[1];
484 data.humidity = observeData[4].split(",")[0].split(" ")[1];
486 data.pressure = observeData[5].split(",")[0].split(" ")[1].split("mB")[0];
488 data.pressureTendency = observeData[5].split(",")[1].trimmed();
490 data.visibilityStr = observeData[6].trimmed();
492 } else {
493 parseUnknownElement(xml);
499 bool UKMETIon::readObservationXMLData(const QString& source, QXmlStreamReader& xml)
501 WeatherData data;
503 while (!xml.atEnd()) {
504 xml.readNext();
506 if (xml.isEndElement()) {
507 break;
510 if (xml.isStartElement()) {
511 if (xml.name() == "rss") {
512 parsePlaceObservation(source, data, xml);
513 } else {
514 parseUnknownElement(xml);
520 d->m_weatherData[source] = data;
522 // Get the 5 day forecast info next.
523 getFiveDayForecast(source);
525 return !xml.error();
528 bool UKMETIon::readFiveDayForecastXMLData(const QString& source, QXmlStreamReader& xml)
530 while (!xml.atEnd()) {
531 xml.readNext();
533 if (xml.isEndElement()) {
534 break;
537 if (xml.isStartElement()) {
538 if (xml.name() == "wml") {
539 parseFiveDayForecast(source, xml);
540 } else {
541 parseUnknownElement(xml);
545 updateWeather(source);
546 return !xml.error();
549 void UKMETIon::parseFiveDayForecast(const QString& source, QXmlStreamReader& xml)
551 Q_ASSERT(xml.isStartElement() && xml.name() == "wml");
553 int currentParagraph = 0;
554 bool skipPlace = false;
555 int dataItem = 0;
556 int numberValue = 0;
558 enum DataItem {
559 Day,
560 Summary,
561 MaxTemp,
562 MinTemp,
563 WindSpeed
566 // Flush out the old forecasts when updating.
567 d->m_weatherData[source].forecasts.clear();
569 WeatherData::ForecastInfo *forecast = new WeatherData::ForecastInfo;
571 QRegExp numParser("(Max|Min|Wind)\\s+-*([0-9]+)");
572 while (!xml.atEnd()) {
573 xml.readNext();
575 if (xml.isStartElement() && xml.name() == "p") {
576 currentParagraph++;
579 if (currentParagraph == 3) {
580 if (xml.isCharacters() && !xml.isWhitespace()) {
581 QString dataText = xml.text().toString().trimmed();
582 if (!skipPlace) {
583 skipPlace = true;
584 } else {
585 if (numParser.indexIn(dataText) != -1 && numParser.capturedTexts().count() >= 3) {
586 numberValue = numParser.capturedTexts()[2].toInt();
588 switch (dataItem) {
589 case Day:
590 forecast->period = dataText;
591 dataItem++;
592 break;
593 case Summary:
594 forecast->summary = dataText;
595 dataItem++;
596 break;
597 case MaxTemp:
598 forecast->tempHigh = numberValue;
599 dataItem++;
600 break;
601 case MinTemp:
602 forecast->tempLow = numberValue;
603 dataItem++;
604 break;
605 case WindSpeed:
606 forecast->windSpeed = numberValue;
607 forecast->windDirection = dataText.split("(")[1].split(")")[0];
608 dataItem = 0;
609 d->m_weatherData[source].forecasts.append(forecast);
610 forecast = new WeatherData::ForecastInfo;
611 break;
618 delete forecast;
621 void UKMETIon::setMeasureUnit(const QString& unitType)
623 d->m_measureType = unitType.toInt();
626 // Not used in this ion yet.
627 void UKMETIon::setTimezoneFormat(const QString& tz)
629 d->m_timezoneType = tz.toInt(); // Boolean
632 bool UKMETIon::metricUnit()
634 if (d->m_measureType == KLocale::Metric) {
635 return true;
638 // Imperial units
639 return false;
642 // Not used in this ion yet.
643 bool UKMETIon::timezone()
645 if (d->m_timezoneType) {
646 return true;
649 // Not UTC, local time
650 return false;
653 void UKMETIon::validate(const QString& source)
655 bool beginflag = true;
657 if (!d->m_locations.count()) {
658 QStringList invalidPlace = source.split('|');
659 if (d->m_place[QString("bbcukmet|%1").arg(invalidPlace[2])].place.isEmpty()) {
660 setData(source, "validate", QString("bbcukmet|invalid|multiple|%1").arg(invalidPlace[2]));
662 d->m_locations.clear();
663 return;
664 } else {
665 QString placeList;
666 foreach(QString place, d->m_locations) {
667 if (beginflag) {
668 placeList.append(QString("%1|extra|%2").arg(place.split("|")[1]).arg(d->m_place[place].XMLurl));
669 beginflag = false;
670 } else {
671 placeList.append(QString("|place|%1|extra|%2").arg(place.split("|")[1]).arg(d->m_place[place].XMLurl));
674 if (d->m_locations.count() > 1) {
675 setData(source, "validate", QString("bbcukmet|valid|multiple|place|%1").arg(placeList));
676 } else {
677 placeList[0] = placeList[0].toUpper();
678 setData(source, "validate", QString("bbcukmet|valid|single|place|%1").arg(placeList));
681 d->m_locations.clear();
684 void UKMETIon::updateWeather(const QString& source)
686 QString weatherSource = source;
687 weatherSource.replace("bbcukmet|", "bbcukmet|weather|");
688 weatherSource.append(QString("|%1").arg(d->m_place[source].XMLurl));
690 QMap<QString, QString> dataFields;
691 QStringList fieldList;
692 QVector<QString> forecastList;
693 int i = 0;
695 setData(weatherSource, "Place", place(source));
696 setData(weatherSource, "Station", station(source));
697 setData(weatherSource, "Observation Period", observationTime(source));
698 setData(weatherSource, "Current Conditions", condition(source));
700 setData(weatherSource, "Humidity", humidity(source));
701 setData(weatherSource, "Visibility", visibility(source));
703 dataFields = temperature(source);
704 setData(weatherSource, "Temperature", dataFields["temperature"]);
705 setData(weatherSource, "Temperature Unit", dataFields["temperatureUnit"]);
707 dataFields = pressure(source);
708 setData(weatherSource, "Pressure", dataFields["pressure"]);
709 setData(weatherSource, "Pressure Unit", dataFields["pressureUnit"]);
710 setData(weatherSource, "Pressure Tendency", dataFields["pressureTendency"]);
712 dataFields = wind(source);
713 setData(weatherSource, "Wind Speed", dataFields["windSpeed"]);
714 setData(weatherSource, "Wind Speed Unit", dataFields["windUnit"]);
715 setData(weatherSource, "Wind Direction", dataFields["windDirection"]);
717 // 5 Day forecast info
718 forecastList = forecasts(source);
720 QString windSpeed;
721 QString windUnit;
722 foreach(QString forecastItem, forecastList) {
723 fieldList = forecastItem.split('|');
724 if (metricUnit()) {
725 windSpeed = QString::number(WeatherFormula::milesToKM(fieldList[4].toFloat()), 'f', 1);
726 windUnit = "km/h";
727 } else {
728 windSpeed = fieldList[4];
729 windUnit = "mph";
732 setData(weatherSource, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7") \
733 .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[2]).arg(fieldList[3]) \
734 .arg(windSpeed).arg(windUnit).arg(fieldList[5]));
735 i++;
738 setData(weatherSource, "Credit", "Supported by backstage.bbc.co.uk / Data from UK MET Office");
741 QString UKMETIon::place(const QString& source)
743 return d->m_weatherData[source].stationName;
746 QString UKMETIon::station(const QString& source)
748 return d->m_weatherData[source].stationName;
751 QString UKMETIon::observationTime(const QString& source)
753 return d->m_weatherData[source].obsTime;
756 QString UKMETIon::condition(const QString& source)
758 return d->m_weatherData[source].condition;
761 QMap<QString, QString> UKMETIon::temperature(const QString& source)
763 QMap<QString, QString> temperatureInfo;
765 if (metricUnit()) {
766 temperatureInfo.insert("temperature", QString("%1").arg(d->m_weatherData[source].temperature_C));
767 temperatureInfo.insert("temperatureUnit", QString("%1C").arg(QChar(176)));
768 } else {
769 temperatureInfo.insert("temperature", QString("%1").arg(d->m_weatherData[source].temperature_F));
770 temperatureInfo.insert("temperatureUnit", QString("%1F").arg(QChar(176)));
772 return temperatureInfo;
775 QMap<QString, QString> UKMETIon::wind(const QString& source)
777 QMap<QString, QString> windInfo;
778 if (d->m_weatherData[source].windSpeed_miles == "N/A") {
779 windInfo.insert("windSpeed", "N/A");
780 windInfo.insert("windUnit", "N/A");
781 } else {
782 if (metricUnit()) {
783 windInfo.insert("windSpeed", QString::number(WeatherFormula::milesToKM(d->m_weatherData[source].windSpeed_miles.toFloat()), 'f', 1));
784 windInfo.insert("windUnit", "km/h");
785 } else {
786 windInfo.insert("windSpeed", QString(d->m_weatherData[source].windSpeed_miles));
787 windInfo.insert("windUnit", "mph");
790 windInfo.insert("windDirection", d->m_weatherData[source].windDirection);
791 return windInfo;
794 QString UKMETIon::humidity(const QString& source)
796 if (d->m_weatherData[source].humidity == "N/A%") {
797 return "N/A";
799 return d->m_weatherData[source].humidity;
802 QString UKMETIon::visibility(const QString& source)
804 return d->m_weatherData[source].visibilityStr;
807 QMap<QString, QString> UKMETIon::pressure(const QString& source)
809 QMap<QString, QString> pressureInfo;
810 if (d->m_weatherData[source].pressure == "N/A") {
811 pressureInfo.insert("pressure", "N/A");
812 return pressureInfo;
815 if (metricUnit()) {
816 pressureInfo.insert("pressure", QString::number(WeatherFormula::millibarsToKilopascals(d->m_weatherData[source].pressure.toFloat()), 'f', 1));
817 pressureInfo.insert("pressureUnit", "kPa");
818 } else {
819 pressureInfo.insert("pressure", QString::number(WeatherFormula::millibarsToInches(d->m_weatherData[source].pressure.toFloat()), 'f', 2));
820 pressureInfo.insert("pressureUnit", "in");
823 pressureInfo.insert("pressureTendency", d->m_weatherData[source].pressureTendency);
824 return pressureInfo;
827 QVector<QString> UKMETIon::forecasts(const QString& source)
829 QVector<QString> forecastData;
831 for (int i = 0; i < d->m_weatherData[source].forecasts.size(); ++i) {
832 forecastData.append(QString("%1|%2|%3|%4|%5|%6") \
833 .arg(d->m_weatherData[source].forecasts[i]->period) \
834 .arg(d->m_weatherData[source].forecasts[i]->summary) \
835 .arg(d->m_weatherData[source].forecasts[i]->tempHigh) \
836 .arg(d->m_weatherData[source].forecasts[i]->tempLow) \
837 .arg(d->m_weatherData[source].forecasts[i]->windSpeed) \
838 .arg(d->m_weatherData[source].forecasts[i]->windDirection));
841 return forecastData;
844 #include "ion_bbcukmet.moc"