1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Shawn Starr <shawn.starr@rogers.com> *
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. *
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. *
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
38 QString XMLforecastURL
;
40 QString sourceOptions
;
45 QHash
<QString
, UKMETIon::Private::XMLMapInfo
> m_place
;
46 QVector
<QString
> m_locations
;
47 QStringList m_matchLocations
;
50 // Weather information
51 QHash
<QString
, WeatherData
> m_weatherData
;
53 // Store KIO jobs - Search list
54 QMap
<KJob
*, QXmlStreamReader
*> m_jobXml
;
55 QMap
<KJob
*, QString
> m_jobList
;
57 QMap
<KJob
*, QXmlStreamReader
*> m_obsJobXml
;
58 QMap
<KJob
*, QString
> m_obsJobList
;
60 QMap
<KJob
*, QXmlStreamReader
*> m_forecastJobXml
;
61 QMap
<KJob
*, QString
> m_forecastJobList
;
64 KIO::TransferJob
*m_job
;
66 QDateTime m_dateFormat
;
71 UKMETIon::UKMETIon(QObject
*parent
, const QVariantList
&args
)
72 : IonInterface(parent
, args
), d(new Private())
80 // Destroy each forecast stored in a QVector
81 foreach(const WeatherData
&item
, d
->m_weatherData
) {
82 foreach(WeatherData::ForecastInfo
*forecast
, item
.forecasts
) {
93 // Get the master list of locations to be parsed
99 QMap
<QString
, IonInterface::ConditionIcons
> UKMETIon::setupDayIconMappings(void)
101 // ClearDay, FewCloudsDay, PartlyCloudyDay, Overcast,
102 // Showers, ScatteredShowers, Thunderstorm, Snow,
103 // FewCloudsNight, PartlyCloudyNight, ClearNight,
104 // Mist, NotAvailable
106 QMap
<QString
, ConditionIcons
> dayList
;
107 dayList
["sunny"] = ClearDay
;
108 //dayList["sunny night"] = ClearNight;
109 dayList
["clear"] = ClearDay
;
110 dayList
["sunny intervals"] = PartlyCloudyDay
;
111 //dayList["sunny intervals night"] = ClearNight;
112 dayList
["partly cloudy"] = PartlyCloudyDay
;
113 dayList
["cloudy"] = Overcast
;
114 //dayList["low level cloud"] = NotAvailable;
115 //dayList["medium level cloud"] = NotAvailable;
116 //dayList["sandstorm"] = NotAvailable;
117 dayList
["drizzle"] = LightRain
;
118 dayList
["misty"] = Mist
;
119 dayList
["mist"] = Mist
;
120 dayList
["fog"] = Mist
;
121 dayList
["foggy"] = Mist
;
122 dayList
["tropical storm"] = Thunderstorm
;
123 dayList
["hazy"] = NotAvailable
;
124 dayList
["light shower"] = Showers
;
125 dayList
["light rain shower"] = Showers
;
126 dayList
["light showers"] = Showers
;
127 dayList
["light rain"] = Showers
;
128 dayList
["heavy rain"] = Rain
;
129 dayList
["heavy showers"] = Rain
;
130 dayList
["heavy shower"] = Rain
;
131 dayList
["thundery shower"] = Thunderstorm
;
132 dayList
["thunderstorm"] = Thunderstorm
;
133 dayList
["cloudy with sleet"] = RainSnow
;
134 dayList
["sleet shower"] = RainSnow
;
135 dayList
["sleet showers"] = RainSnow
;
136 dayList
["sleet"] = RainSnow
;
137 dayList
["cloudy with hail"] = Hail
;
138 dayList
["hail shower"] = Hail
;
139 dayList
["hail showers"] = Hail
;
140 dayList
["hail"] = Hail
;
141 dayList
["light snow"] = LightSnow
;
142 dayList
["light snow shower"] = Flurries
;
143 dayList
["light snow showers"] = Flurries
;
144 dayList
["cloudy with light snow"] = LightSnow
;
145 dayList
["heavy snow"] = Snow
;
146 dayList
["heavy snow shower"] = Snow
;
147 dayList
["heavy snow showers"] = Snow
;
148 dayList
["cloudy with heavy snow"] = Snow
;
149 dayList
["na"] = NotAvailable
;
153 QMap
<QString
, IonInterface::ConditionIcons
> UKMETIon::setupNightIconMappings(void)
155 QMap
<QString
, ConditionIcons
> nightList
;
156 nightList
["clear"] = ClearNight
;
157 nightList
["clear intervals"] = PartlyCloudyNight
;
158 nightList
["sunny intervals"] = PartlyCloudyDay
; // it's not really sunny
159 nightList
["sunny"] = ClearDay
;
160 nightList
["cloudy"] = Overcast
;
161 nightList
["partly cloudy"] = PartlyCloudyNight
;
162 nightList
["drizzle"] = LightRain
;
163 nightList
["misty"] = Mist
;
164 nightList
["mist"] = Mist
;
165 nightList
["fog"] = Mist
;
166 nightList
["foggy"] = Mist
;
167 nightList
["tropical storm"] = Thunderstorm
;
168 nightList
["hazy"] = NotAvailable
;
169 nightList
["light shower"] = Showers
;
170 nightList
["light rain shower"] = Showers
;
171 nightList
["light showers"] = Showers
;
172 nightList
["light rain"] = Showers
;
173 nightList
["heavy rain"] = Rain
;
174 nightList
["heavy showers"] = Rain
;
175 nightList
["heavy shower"] = Rain
;
176 nightList
["thundery shower"] = Thunderstorm
;
177 nightList
["thunderstorm"] = Thunderstorm
;
178 nightList
["cloudy with sleet"] = NotAvailable
;
179 nightList
["sleet shower"] = NotAvailable
;
180 nightList
["sleet showers"] = NotAvailable
;
181 nightList
["sleet"] = NotAvailable
;
182 nightList
["cloudy with hail"] = Hail
;
183 nightList
["hail shower"] = Hail
;
184 nightList
["hail showers"] = Hail
;
185 nightList
["hail"] = Hail
;
186 nightList
["light snow"] = LightSnow
;
187 nightList
["light snow shower"] = Flurries
;
188 nightList
["light snow showers"] = Flurries
;
189 nightList
["cloudy with light snow"] = LightSnow
;
190 nightList
["heavy snow"] = Snow
;
191 nightList
["heavy snow shower"] = Snow
;
192 nightList
["heavy snow showers"] = Snow
;
193 nightList
["cloudy with heavy snow"] = Snow
;
194 nightList
["na"] = NotAvailable
;
199 QMap
<QString
, IonInterface::ConditionIcons
> const& UKMETIon::dayIcons(void)
201 static QMap
<QString
, ConditionIcons
> const dval
= setupDayIconMappings();
205 QMap
<QString
, IonInterface::ConditionIcons
> const& UKMETIon::nightIcons(void)
207 static QMap
<QString
, ConditionIcons
> const nval
= setupNightIconMappings();
211 // Get a specific Ion's data
212 bool UKMETIon::updateIonSource(const QString
& source
)
214 // We expect the applet to send the source in the following tokenization:
215 // ionname|validate|place_name - Triggers validation of place
216 // ionname|weather|place_name - Triggers receiving weather of place
218 QStringList sourceAction
= source
.split('|');
220 if (sourceAction
[1] == QString("validate")) {
221 // Look for places to match
222 findPlace(sourceAction
[2], source
);
225 } else if (sourceAction
[1] == QString("weather")) {
226 if (sourceAction
.count() >= 3) {
227 d
->m_place
[QString("bbcukmet|%1").arg(sourceAction
[2])].XMLurl
= sourceAction
[3];
228 getXMLData(QString("%1|%2").arg(sourceAction
[0]).arg(sourceAction
[2]));
237 // Gets specific city XML data
238 void UKMETIon::getXMLData(const QString
& source
)
241 url
= d
->m_place
[source
].XMLurl
;
243 d
->m_job
= KIO::get(url
.url(), KIO::Reload
, KIO::HideProgressInfo
);
244 d
->m_job
->addMetaData("cookies", "none"); // Disable displaying cookies
245 d
->m_obsJobXml
.insert(d
->m_job
, new QXmlStreamReader
);
246 d
->m_obsJobList
.insert(d
->m_job
, source
);
249 connect(d
->m_job
, SIGNAL(data(KIO::Job
*, const QByteArray
&)), this,
250 SLOT(observation_slotDataArrived(KIO::Job
*, const QByteArray
&)));
251 connect(d
->m_job
, SIGNAL(result(KJob
*)), this, SLOT(observation_slotJobFinished(KJob
*)));
255 // Parses city list and gets the correct city based on ID number
256 void UKMETIon::findPlace(const QString
& place
, const QString
& source
)
259 url
= "http://www.bbc.co.uk/cgi-perl/weather/search/new_search.pl?x=0&y=0&=Submit&search_query=" + place
+ "&tmpl=wap";
261 d
->m_job
= KIO::get(url
.url(), KIO::Reload
, KIO::HideProgressInfo
);
262 d
->m_job
->addMetaData("cookies", "none"); // Disable displaying cookies
263 d
->m_jobXml
.insert(d
->m_job
, new QXmlStreamReader
);
264 d
->m_jobList
.insert(d
->m_job
, source
);
267 connect(d
->m_job
, SIGNAL(data(KIO::Job
*, const QByteArray
&)), this,
268 SLOT(setup_slotDataArrived(KIO::Job
*, const QByteArray
&)));
269 connect(d
->m_job
, SIGNAL(result(KJob
*)), this, SLOT(setup_slotJobFinished(KJob
*)));
271 // Handle redirects for direct hit places.
272 connect(d
->m_job
, SIGNAL(redirection(KIO::Job
*, const KUrl
&)), this,
273 SLOT(setup_slotRedirected(KIO::Job
*, const KUrl
&)));
277 void UKMETIon::getFiveDayForecast(const QString
& source
)
280 url
= d
->m_place
[source
].XMLforecastURL
;
281 QString xmlMap
= d
->m_place
[source
].XMLforecastURL
;
282 xmlMap
.replace("weather/5day.shtml", "weather/mobile/5day.wml");
285 d
->m_job
= KIO::get(url
.url(), KIO::Reload
, KIO::HideProgressInfo
);
286 d
->m_job
->addMetaData("cookies", "none"); // Disable displaying cookies
287 d
->m_forecastJobXml
.insert(d
->m_job
, new QXmlStreamReader
);
288 d
->m_forecastJobList
.insert(d
->m_job
, source
);
291 connect(d
->m_job
, SIGNAL(data(KIO::Job
*, const QByteArray
&)), this,
292 SLOT(forecast_slotDataArrived(KIO::Job
*, const QByteArray
&)));
293 connect(d
->m_job
, SIGNAL(result(KJob
*)), this, SLOT(forecast_slotJobFinished(KJob
*)));
297 bool UKMETIon::readSearchXMLData(const QString
& key
, QXmlStreamReader
& xml
)
300 while (!xml
.atEnd()) {
303 if (xml
.isEndElement()) {
307 if (xml
.isStartElement()) {
308 if (xml
.name() == "wml") {
309 parseSearchLocations(key
, xml
);
311 parseUnknownElement(xml
);
319 void UKMETIon::parseSearchLocations(const QString
& source
, QXmlStreamReader
& xml
)
327 int currentParagraph
= 0;
329 Q_ASSERT(xml
.isStartElement() && xml
.name() == "wml");
331 while (!xml
.atEnd()) {
334 if (xml
.isEndElement() && xml
.name() == "wml") {
338 if (xml
.isStartElement() && xml
.name() == "p") {
342 if (currentParagraph
== 2) {
343 if (xml
.isCharacters() && !xml
.isWhitespace()) {
344 QString dataText
= xml
.text().toString().trimmed();
345 if (dataText
.contains("No locations")) {
351 if (xml
.isStartElement()) {
352 if (xml
.name() == "a" && !xml
.attributes().value("href").isEmpty()) {
353 if (xml
.attributes().value("href").toString().contains("5day.wml")) {
355 // Split URL to determine station ID number
356 tokens
= xml
.attributes().value("href").toString().split('=');
357 if (xml
.attributes().value("href").toString().contains("world")) {
358 url
= "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens
[1] + ".xml";
361 url
= "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens
[1] + ".xml";
364 place
= xml
.readElementText();
365 tmp
= QString("bbcukmet|%1").arg(place
);
367 // Duplicate places can exist
368 if (d
->m_locations
.contains(tmp
)) {
370 QString dupePlace
= place
;
371 tmp
= QString("bbcukmet|%1").arg(QString("%1 (#%2)").arg(dupePlace
).arg(counter
));
372 place
= QString("%1 (#%2)").arg(dupePlace
).arg(counter
);
376 if (flag
) { // This is a UK specific location
377 d
->m_place
[tmp
].XMLurl
= url
;
378 d
->m_place
[tmp
].place
= place
;
379 d
->m_place
[tmp
].ukPlace
= true;
381 d
->m_place
[tmp
].XMLurl
= url
;
382 d
->m_place
[tmp
].place
= place
;
383 d
->m_place
[tmp
].ukPlace
= false;
385 d
->m_locations
.append(tmp
);
393 // handle when no XML tag is found
394 void UKMETIon::parseUnknownElement(QXmlStreamReader
& xml
)
396 while (!xml
.atEnd()) {
399 if (xml
.isEndElement()) {
403 if (xml
.isStartElement()) {
404 parseUnknownElement(xml
);
409 void UKMETIon::setup_slotRedirected(KIO::Job
*job
, const KUrl
&url
)
415 QStringList tokens
= url
.url().split('=');
416 if (url
.url().contains("xhtml")) { // We don't care about the first redirection (there is two)
417 if (url
.url().contains("world")) {
418 obsUrl
= "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens
[2] + ".xml";
421 obsUrl
= "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens
[2] + ".xml";
424 place
= d
->m_jobList
[job
].split('|')[2]; // Contains the source name (place in this case)
425 tmp
= QString("bbcukmet|%1").arg(place
);
426 place
[0] = place
[0].toUpper();
428 if (flag
) { // This is a UK specific location
429 d
->m_place
[tmp
].XMLurl
= obsUrl
;
430 d
->m_place
[tmp
].place
= place
;
431 d
->m_place
[tmp
].ukPlace
= true;
433 d
->m_place
[tmp
].XMLurl
= obsUrl
;
434 d
->m_place
[tmp
].place
= place
;
435 d
->m_place
[tmp
].ukPlace
= false;
437 d
->m_locations
.append(tmp
);
438 validate(d
->m_jobList
[job
]);
442 void UKMETIon::setup_slotDataArrived(KIO::Job
*job
, const QByteArray
&data
)
444 QByteArray local
= data
;
445 if (data
.isEmpty() || !d
->m_jobXml
.contains(job
)) {
449 // XXX: BBC doesn't convert unicode strings so this breaks XML formatting. Not pretty.
450 if (local
.startsWith("<?xml version")) {
451 local
.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
455 d
->m_jobXml
[job
]->addData(local
);
458 void UKMETIon::setup_slotJobFinished(KJob
*job
)
460 if (job
->error() == 149) {
461 setData(d
->m_jobList
[job
], "validate", QString("bbcukmet|timeout"));
462 disconnectSource(d
->m_jobList
[job
], this);
463 d
->m_jobList
.remove(job
);
464 delete d
->m_jobXml
[job
];
465 d
->m_jobXml
.remove(job
);
468 // If Redirected, don't go to this routine
469 if (!d
->m_locations
.contains(QString("bbcukmet|%1").arg(d
->m_jobList
[job
]))) {
470 readSearchXMLData(d
->m_jobList
[job
], *d
->m_jobXml
[job
]);
472 d
->m_jobList
.remove(job
);
473 delete d
->m_jobXml
[job
];
474 d
->m_jobXml
.remove(job
);
477 void UKMETIon::observation_slotDataArrived(KIO::Job
*job
, const QByteArray
&data
)
479 QByteArray local
= data
;
480 if (data
.isEmpty() || !d
->m_obsJobXml
.contains(job
)) {
484 // XXX: I don't know what to say about this. But horrible. We can't really do much about this :/
485 // No, it's not UTF-8, it really lies.
486 if (local
.startsWith("<?xml version")) {
487 local
.replace("encoding=\"UTF-8\"?>", "encoding=\"cp1252\" ?>");
491 d
->m_obsJobXml
[job
]->addData(local
);
494 void UKMETIon::observation_slotJobFinished(KJob
*job
)
496 setData(d
->m_obsJobList
[job
], Data());
497 readObservationXMLData(d
->m_obsJobList
[job
], *d
->m_obsJobXml
[job
]);
498 d
->m_obsJobList
.remove(job
);
499 delete d
->m_obsJobXml
[job
];
500 d
->m_obsJobXml
.remove(job
);
503 void UKMETIon::forecast_slotDataArrived(KIO::Job
*job
, const QByteArray
&data
)
505 QByteArray local
= data
;
506 if (data
.isEmpty() || !d
->m_forecastJobXml
.contains(job
)) {
510 // XXX: BBC doesn't convert unicode strings so this breaks XML formatting. Not pretty.
511 // No, it's not UTF-8, it really lies.
512 if (local
.startsWith("<?xml version")) {
513 local
.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
516 d
->m_forecastJobXml
[job
]->addData(local
);
519 void UKMETIon::forecast_slotJobFinished(KJob
*job
)
521 setData(d
->m_forecastJobList
[job
], Data());
522 readFiveDayForecastXMLData(d
->m_forecastJobList
[job
], *d
->m_forecastJobXml
[job
]);
523 d
->m_forecastJobList
.remove(job
);
524 delete d
->m_forecastJobXml
[job
];
525 d
->m_forecastJobXml
.remove(job
);
528 void UKMETIon::parsePlaceObservation(const QString
&source
, WeatherData
& data
, QXmlStreamReader
& xml
)
530 Q_ASSERT(xml
.isStartElement() && xml
.name() == "rss");
532 while (!xml
.atEnd()) {
535 if (xml
.isEndElement() && xml
.name() == "rss") {
539 if (xml
.isStartElement()) {
540 if (xml
.name() == "channel") {
541 parseWeatherChannel(source
, data
, xml
);
547 void UKMETIon::parseWeatherChannel(const QString
& source
, WeatherData
& data
, QXmlStreamReader
& xml
)
549 Q_ASSERT(xml
.isStartElement() && xml
.name() == "channel");
551 while (!xml
.atEnd()) {
554 if (xml
.isEndElement() && xml
.name() == "channel") {
558 if (xml
.isStartElement()) {
559 if (xml
.name() == "title") {
560 data
.stationName
= xml
.readElementText().split("Observations for")[1].trimmed();
562 data
.stationName
.replace("United Kingdom", "UK");
563 data
.stationName
.replace("United States of America", "USA");
565 } else if (xml
.name() == "item") {
566 parseWeatherObservation(source
, data
, xml
);
568 parseUnknownElement(xml
);
574 void UKMETIon::parseWeatherObservation(const QString
& source
, WeatherData
& data
, QXmlStreamReader
& xml
)
577 Q_ASSERT(xml
.isStartElement() && xml
.name() == "item");
579 while (!xml
.atEnd()) {
582 if (xml
.isEndElement() && xml
.name() == "item") {
586 if (xml
.isStartElement()) {
587 if (xml
.name() == "title") {
588 QString conditionString
= xml
.readElementText();
590 // Get the observation time.
591 QStringList conditionData
= conditionString
.split(':');
593 data
.obsTime
= conditionData
[0];
594 // Friday at 0200 GMT
595 d
->m_dateFormat
= QDateTime::fromString(data
.obsTime
.split("at")[1].trimmed(), "hhmm 'GMT'");
596 data
.iconPeriodHour
= d
->m_dateFormat
.toString("HH").toInt();
597 //data.iconPeriodAP = d->m_dateFormat.toString("ap");
599 data
.condition
= conditionData
[1].split('.')[0].trimmed();
601 } else if (xml
.name() == "link") {
602 d
->m_place
[source
].XMLforecastURL
= xml
.readElementText();
603 } else if (xml
.name() == "description") {
604 QString observeString
= xml
.readElementText();
605 QStringList observeData
= observeString
.split(':');
607 data
.temperature_C
= observeData
[1].split(QChar(176))[0].trimmed();
608 data
.temperature_F
= observeData
[1].split('(')[1].split(QChar(176))[0];
610 data
.windDirection
= observeData
[2].split(',')[0].trimmed();
611 data
.windSpeed_miles
= observeData
[3].split(',')[0].split(' ')[1];
613 data
.humidity
= observeData
[4].split(',')[0].split(' ')[1];
615 data
.pressure
= observeData
[5].split(',')[0].split(' ')[1].split("mB")[0];
617 data
.pressureTendency
= observeData
[5].split(',')[1].trimmed();
619 data
.visibilityStr
= observeData
[6].trimmed();
622 parseUnknownElement(xml
);
628 bool UKMETIon::readObservationXMLData(const QString
& source
, QXmlStreamReader
& xml
)
632 while (!xml
.atEnd()) {
635 if (xml
.isEndElement()) {
639 if (xml
.isStartElement()) {
640 if (xml
.name() == "rss") {
641 parsePlaceObservation(source
, data
, xml
);
643 parseUnknownElement(xml
);
649 d
->m_weatherData
[source
] = data
;
651 // Get the 5 day forecast info next.
652 getFiveDayForecast(source
);
657 bool UKMETIon::readFiveDayForecastXMLData(const QString
& source
, QXmlStreamReader
& xml
)
659 while (!xml
.atEnd()) {
662 if (xml
.isEndElement()) {
666 if (xml
.isStartElement()) {
667 if (xml
.name() == "wml") {
668 parseFiveDayForecast(source
, xml
);
670 parseUnknownElement(xml
);
674 updateWeather(source
);
678 void UKMETIon::parseFiveDayForecast(const QString
& source
, QXmlStreamReader
& xml
)
680 Q_ASSERT(xml
.isStartElement() && xml
.name() == "wml");
681 bool validNumber
= false;
682 int currentParagraph
= 0;
683 bool skipPlace
= false;
694 // Flush out the old forecasts when updating.
695 d
->m_weatherData
[source
].forecasts
.clear();
697 WeatherData::ForecastInfo
*forecast
= new WeatherData::ForecastInfo
;
699 QRegExp
numParser("(Max|Min|Wind)\\s+-*([0-9]+)");
700 while (!xml
.atEnd()) {
703 if (xml
.isStartElement() && xml
.name() == "p") {
707 if (currentParagraph
== 3) {
708 if (xml
.isCharacters() && !xml
.isWhitespace()) {
709 QString dataText
= xml
.text().toString().trimmed();
713 if (numParser
.indexIn(dataText
) != -1 && numParser
.capturedTexts().count() >= 3) {
718 forecast
->period
= dataText
;
722 forecast
->summary
= dataText
;
723 forecast
->iconName
= getWeatherIcon(dayIcons(), forecast
->summary
.toLower());
727 forecast
->tempHigh
= numParser
.capturedTexts()[0].remove("Max").toInt();
732 forecast
->tempLow
= numParser
.capturedTexts()[0].remove("Min").toInt();
737 forecast
->windSpeed
= numParser
.capturedTexts()[0].remove("Wind").toInt();
738 forecast
->windDirection
= dataText
.split('(')[1].split(')')[0];
740 d
->m_weatherData
[source
].forecasts
.append(forecast
);
741 forecast
= new WeatherData::ForecastInfo
;
753 void UKMETIon::validate(const QString
& source
)
755 bool beginflag
= true;
757 if (!d
->m_locations
.count()) {
758 QStringList invalidPlace
= source
.split('|');
759 if (d
->m_place
[QString("bbcukmet|%1").arg(invalidPlace
[2])].place
.isEmpty()) {
760 setData(source
, "validate", QString("bbcukmet|invalid|multiple|%1").arg(invalidPlace
[2]));
762 d
->m_locations
.clear();
766 foreach(const QString
&place
, d
->m_locations
) {
768 placeList
.append(QString("%1|extra|%2").arg(place
.split('|')[1]).arg(d
->m_place
[place
].XMLurl
));
771 placeList
.append(QString("|place|%1|extra|%2").arg(place
.split('|')[1]).arg(d
->m_place
[place
].XMLurl
));
774 if (d
->m_locations
.count() > 1) {
775 setData(source
, "validate", QString("bbcukmet|valid|multiple|place|%1").arg(placeList
));
777 placeList
[0] = placeList
[0].toUpper();
778 setData(source
, "validate", QString("bbcukmet|valid|single|place|%1").arg(placeList
));
781 d
->m_locations
.clear();
784 void UKMETIon::updateWeather(const QString
& source
)
786 QString weatherSource
= source
;
787 weatherSource
.replace("bbcukmet|", "bbcukmet|weather|");
788 weatherSource
.append(QString("|%1").arg(d
->m_place
[source
].XMLurl
));
790 QMap
<QString
, QString
> dataFields
;
791 QStringList fieldList
;
792 QVector
<QString
> forecastList
;
795 setData(weatherSource
, "Place", place(source
));
796 setData(weatherSource
, "Station", station(source
));
797 setData(weatherSource
, "Observation Period", observationTime(source
));
798 setData(weatherSource
, "Current Conditions", condition(source
));
800 // Tell applet which icon to use for conditions and provide mapping for condition type to the icons to display
801 if (periodHour(source
) >= 0 && periodHour(source
) < 6) {
802 setData(weatherSource
, "Condition Icon", getWeatherIcon(nightIcons(), condition(source
)));
803 } else if (periodHour(source
) >= 18) {
804 setData(weatherSource
, "Condition Icon", getWeatherIcon(nightIcons(), condition(source
)));
806 setData(weatherSource
, "Condition Icon", getWeatherIcon(dayIcons(), condition(source
)));
809 setData(weatherSource
, "Humidity", humidity(source
));
810 setData(weatherSource
, "Visibility", visibility(source
));
812 dataFields
= temperature(source
);
813 setData(weatherSource
, "Temperature", dataFields
["temperature"]);
814 setData(weatherSource
, "Temperature Unit", dataFields
["temperatureUnit"]);
816 dataFields
= pressure(source
);
817 setData(weatherSource
, "Pressure", dataFields
["pressure"]);
818 setData(weatherSource
, "Pressure Unit", dataFields
["pressureUnit"]);
819 setData(weatherSource
, "Pressure Tendency", dataFields
["pressureTendency"]);
821 dataFields
= wind(source
);
822 setData(weatherSource
, "Wind Speed", dataFields
["windSpeed"]);
823 setData(weatherSource
, "Wind Speed Unit", dataFields
["windUnit"]);
824 setData(weatherSource
, "Wind Direction", dataFields
["windDirection"]);
826 // 5 Day forecast info
827 forecastList
= forecasts(source
);
829 // Set number of forecasts per day/night supported
830 setData(weatherSource
, QString("Total Weather Days"), d
->m_weatherData
[source
].forecasts
.size());
832 foreach(const QString
&forecastItem
, forecastList
) {
833 fieldList
= forecastItem
.split('|');
835 setData(weatherSource
, QString("Short Forecast Day %1").arg(i
), QString("%1|%2|%3|%4|%5|%6") \
836 .arg(fieldList
[0]).arg(fieldList
[1]).arg(fieldList
[2]).arg(fieldList
[3]) \
837 .arg(fieldList
[4]).arg(fieldList
[5]));
841 setData(weatherSource
, "Credit", "Supported by backstage.bbc.co.uk / Data from UK MET Office");
842 setData(weatherSource
, "Credit Url", d
->m_place
[source
].XMLforecastURL
);
845 QString
UKMETIon::place(const QString
& source
)
847 return d
->m_weatherData
[source
].stationName
;
850 QString
UKMETIon::station(const QString
& source
)
852 return d
->m_weatherData
[source
].stationName
;
855 QString
UKMETIon::observationTime(const QString
& source
)
857 return d
->m_weatherData
[source
].obsTime
;
861 bool UKMETIon::night(const QString& source)
863 if (d->m_weatherData[source].iconPeriodAP == "pm") {
869 int UKMETIon::periodHour(const QString
& source
)
871 return d
->m_weatherData
[source
].iconPeriodHour
;
874 QString
UKMETIon::condition(const QString
& source
)
876 return d
->m_weatherData
[source
].condition
;
879 QMap
<QString
, QString
> UKMETIon::temperature(const QString
& source
)
881 QMap
<QString
, QString
> temperatureInfo
;
883 temperatureInfo
.insert("temperature", QString(d
->m_weatherData
[source
].temperature_C
));
884 temperatureInfo
.insert("temperatureUnit", QString::number(WeatherUtils::Celsius
));
885 return temperatureInfo
;
888 QMap
<QString
, QString
> UKMETIon::wind(const QString
& source
)
890 QMap
<QString
, QString
> windInfo
;
891 if (d
->m_weatherData
[source
].windSpeed_miles
== "N/A") {
892 windInfo
.insert("windSpeed", "N/A");
893 windInfo
.insert("windUnit", QString::number(WeatherUtils::NoUnit
));
895 windInfo
.insert("windSpeed", QString(d
->m_weatherData
[source
].windSpeed_miles
));
896 windInfo
.insert("windUnit", QString::number(WeatherUtils::MilesAnHour
));
898 windInfo
.insert("windDirection", d
->m_weatherData
[source
].windDirection
);
902 QString
UKMETIon::humidity(const QString
& source
)
904 if (d
->m_weatherData
[source
].humidity
== "N/A%") {
907 return d
->m_weatherData
[source
].humidity
;
910 QString
UKMETIon::visibility(const QString
& source
)
912 return d
->m_weatherData
[source
].visibilityStr
;
915 QMap
<QString
, QString
> UKMETIon::pressure(const QString
& source
)
917 QMap
<QString
, QString
> pressureInfo
;
918 if (d
->m_weatherData
[source
].pressure
== "N/A") {
919 pressureInfo
.insert("pressure", "N/A");
923 pressureInfo
.insert("pressure", QString(d
->m_weatherData
[source
].pressure
));
924 pressureInfo
.insert("pressureUnit", QString::number(WeatherUtils::Millibars
));
926 pressureInfo
.insert("pressureTendency", d
->m_weatherData
[source
].pressureTendency
);
930 QVector
<QString
> UKMETIon::forecasts(const QString
& source
)
932 QVector
<QString
> forecastData
;
934 for (int i
= 0; i
< d
->m_weatherData
[source
].forecasts
.size(); ++i
) {
936 if (d
->m_weatherData
[source
].forecasts
[i
]->period
.contains("Saturday")) {
937 d
->m_weatherData
[source
].forecasts
[i
]->period
.replace("Saturday", "Sat");
940 if (d
->m_weatherData
[source
].forecasts
[i
]->period
.contains("Sunday")) {
941 d
->m_weatherData
[source
].forecasts
[i
]->period
.replace("Sunday", "Sun");
944 if (d
->m_weatherData
[source
].forecasts
[i
]->period
.contains("Monday")) {
945 d
->m_weatherData
[source
].forecasts
[i
]->period
.replace("Monday", "Mon");
948 if (d
->m_weatherData
[source
].forecasts
[i
]->period
.contains("Tuesday")) {
949 d
->m_weatherData
[source
].forecasts
[i
]->period
.replace("Tuesday", "Tue");
952 if (d
->m_weatherData
[source
].forecasts
[i
]->period
.contains("Wednesday")) {
953 d
->m_weatherData
[source
].forecasts
[i
]->period
.replace("Wednesday", "Wed");
956 if (d
->m_weatherData
[source
].forecasts
[i
]->period
.contains("Thursday")) {
957 d
->m_weatherData
[source
].forecasts
[i
]->period
.replace("Thursday", "Thu");
959 if (d
->m_weatherData
[source
].forecasts
[i
]->period
.contains("Friday")) {
960 d
->m_weatherData
[source
].forecasts
[i
]->period
.replace("Friday", "Fri");
963 forecastData
.append(QString("%1|%2|%3|%4|%5|%6") \
964 .arg(d
->m_weatherData
[source
].forecasts
[i
]->period
) \
965 .arg(d
->m_weatherData
[source
].forecasts
[i
]->iconName
) \
966 .arg(d
->m_weatherData
[source
].forecasts
[i
]->summary
) \
967 .arg(d
->m_weatherData
[source
].forecasts
[i
]->tempHigh
) \
968 .arg(d
->m_weatherData
[source
].forecasts
[i
]->tempLow
) \
970 //.arg(d->m_weatherData[source].forecasts[i]->windSpeed)
971 //arg(d->m_weatherData[source].forecasts[i]->windDirection));
977 #include "ion_bbcukmet.moc"