00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ion_bbcukmet.h"
00023
00024 class UKMETIon::Private : public QObject
00025 {
00026 public:
00027 Private() {
00028 m_url = 0;
00029 }
00030 ~Private() {
00031 delete m_url;
00032 }
00033
00034 private:
00035 struct XMLMapInfo {
00036 QString place;
00037 QString XMLurl;
00038 QString XMLforecastURL;
00039 bool ukPlace;
00040 QString sourceOptions;
00041 };
00042
00043 public:
00044
00045 QHash<QString, UKMETIon::Private::XMLMapInfo> m_place;
00046 QVector<QString> m_locations;
00047 QStringList m_matchLocations;
00048
00049 public:
00050
00051 QHash<QString, WeatherData> m_weatherData;
00052
00053
00054 QMap<KJob *, QXmlStreamReader*> m_jobXml;
00055 QMap<KJob *, QString> m_jobList;
00056
00057 QMap<KJob *, QXmlStreamReader*> m_obsJobXml;
00058 QMap<KJob *, QString> m_obsJobList;
00059
00060 QMap<KJob *, QXmlStreamReader *> m_forecastJobXml;
00061 QMap<KJob *, QString> m_forecastJobList;
00062
00063 KUrl *m_url;
00064 KIO::TransferJob *m_job;
00065
00066 QDateTime m_dateFormat;
00067 };
00068
00069
00070
00071 UKMETIon::UKMETIon(QObject *parent, const QVariantList &args)
00072 : IonInterface(parent, args), d(new Private())
00073
00074 {
00075 Q_UNUSED(args)
00076 }
00077
00078 UKMETIon::~UKMETIon()
00079 {
00080
00081 foreach(const WeatherData &item, d->m_weatherData) {
00082 foreach(WeatherData::ForecastInfo *forecast, item.forecasts) {
00083 if (forecast) {
00084 delete forecast;
00085 }
00086 }
00087 }
00088
00089
00090 delete d;
00091 }
00092
00093
00094 void UKMETIon::init()
00095 {
00096 setInitialized(true);
00097 }
00098
00099 QMap<QString, IonInterface::ConditionIcons> UKMETIon::setupDayIconMappings(void)
00100 {
00101
00102
00103
00104
00105
00106 QMap<QString, ConditionIcons> dayList;
00107 dayList["sunny"] = ClearDay;
00108
00109 dayList["clear"] = ClearDay;
00110 dayList["sunny intervals"] = PartlyCloudyDay;
00111
00112 dayList["partly cloudy"] = PartlyCloudyDay;
00113 dayList["cloudy"] = Overcast;
00114
00115
00116
00117 dayList["drizzle"] = LightRain;
00118 dayList["misty"] = Mist;
00119 dayList["mist"] = Mist;
00120 dayList["fog"] = Mist;
00121 dayList["foggy"] = Mist;
00122 dayList["tropical storm"] = Thunderstorm;
00123 dayList["hazy"] = NotAvailable;
00124 dayList["light shower"] = Showers;
00125 dayList["light rain shower"] = Showers;
00126 dayList["light showers"] = Showers;
00127 dayList["light rain"] = Showers;
00128 dayList["heavy rain"] = Rain;
00129 dayList["heavy showers"] = Rain;
00130 dayList["heavy shower"] = Rain;
00131 dayList["thundery shower"] = Thunderstorm;
00132 dayList["thunderstorm"] = Thunderstorm;
00133 dayList["cloudy with sleet"] = RainSnow;
00134 dayList["sleet shower"] = RainSnow;
00135 dayList["sleet showers"] = RainSnow;
00136 dayList["sleet"] = RainSnow;
00137 dayList["cloudy with hail"] = Hail;
00138 dayList["hail shower"] = Hail;
00139 dayList["hail showers"] = Hail;
00140 dayList["hail"] = Hail;
00141 dayList["light snow"] = LightSnow;
00142 dayList["light snow shower"] = Flurries;
00143 dayList["light snow showers"] = Flurries;
00144 dayList["cloudy with light snow"] = LightSnow;
00145 dayList["heavy snow"] = Snow;
00146 dayList["heavy snow shower"] = Snow;
00147 dayList["heavy snow showers"] = Snow;
00148 dayList["cloudy with heavy snow"] = Snow;
00149 dayList["na"] = NotAvailable;
00150 return dayList;
00151 }
00152
00153 QMap<QString, IonInterface::ConditionIcons> UKMETIon::setupNightIconMappings(void)
00154 {
00155 QMap<QString, ConditionIcons> nightList;
00156 nightList["clear"] = ClearNight;
00157 nightList["clear intervals"] = PartlyCloudyNight;
00158 nightList["sunny intervals"] = PartlyCloudyDay;
00159 nightList["sunny"] = ClearDay;
00160 nightList["cloudy"] = Overcast;
00161 nightList["partly cloudy"] = PartlyCloudyNight;
00162 nightList["drizzle"] = LightRain;
00163 nightList["misty"] = Mist;
00164 nightList["mist"] = Mist;
00165 nightList["fog"] = Mist;
00166 nightList["foggy"] = Mist;
00167 nightList["tropical storm"] = Thunderstorm;
00168 nightList["hazy"] = NotAvailable;
00169 nightList["light shower"] = Showers;
00170 nightList["light rain shower"] = Showers;
00171 nightList["light showers"] = Showers;
00172 nightList["light rain"] = Showers;
00173 nightList["heavy rain"] = Rain;
00174 nightList["heavy showers"] = Rain;
00175 nightList["heavy shower"] = Rain;
00176 nightList["thundery shower"] = Thunderstorm;
00177 nightList["thunderstorm"] = Thunderstorm;
00178 nightList["cloudy with sleet"] = NotAvailable;
00179 nightList["sleet shower"] = NotAvailable;
00180 nightList["sleet showers"] = NotAvailable;
00181 nightList["sleet"] = NotAvailable;
00182 nightList["cloudy with hail"] = Hail;
00183 nightList["hail shower"] = Hail;
00184 nightList["hail showers"] = Hail;
00185 nightList["hail"] = Hail;
00186 nightList["light snow"] = LightSnow;
00187 nightList["light snow shower"] = Flurries;
00188 nightList["light snow showers"] = Flurries;
00189 nightList["cloudy with light snow"] = LightSnow;
00190 nightList["heavy snow"] = Snow;
00191 nightList["heavy snow shower"] = Snow;
00192 nightList["heavy snow showers"] = Snow;
00193 nightList["cloudy with heavy snow"] = Snow;
00194 nightList["na"] = NotAvailable;
00195
00196 return nightList;
00197 }
00198
00199 QMap<QString, IonInterface::ConditionIcons> const& UKMETIon::dayIcons(void)
00200 {
00201 static QMap<QString, ConditionIcons> const dval = setupDayIconMappings();
00202 return dval;
00203 }
00204
00205 QMap<QString, IonInterface::ConditionIcons> const& UKMETIon::nightIcons(void)
00206 {
00207 static QMap<QString, ConditionIcons> const nval = setupNightIconMappings();
00208 return nval;
00209 }
00210
00211
00212 bool UKMETIon::updateIonSource(const QString& source)
00213 {
00214
00215
00216
00217
00218 QStringList sourceAction = source.split('|');
00219
00220 if (sourceAction[1] == QString("validate")) {
00221
00222 findPlace(sourceAction[2], source);
00223 return true;
00224
00225 } else if (sourceAction[1] == QString("weather")) {
00226 if (sourceAction.count() >= 3) {
00227 d->m_place[QString("bbcukmet|%1").arg(sourceAction[2])].XMLurl = sourceAction[3];
00228 getXMLData(QString("%1|%2").arg(sourceAction[0]).arg(sourceAction[2]));
00229 return true;
00230 } else {
00231 return false;
00232 }
00233 }
00234 return false;
00235 }
00236
00237
00238 void UKMETIon::getXMLData(const QString& source)
00239 {
00240 KUrl url;
00241 url = d->m_place[source].XMLurl;
00242
00243 d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
00244 d->m_job->addMetaData("cookies", "none");
00245 d->m_obsJobXml.insert(d->m_job, new QXmlStreamReader);
00246 d->m_obsJobList.insert(d->m_job, source);
00247
00248 if (d->m_job) {
00249 connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00250 SLOT(observation_slotDataArrived(KIO::Job *, const QByteArray &)));
00251 connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(observation_slotJobFinished(KJob *)));
00252 }
00253 }
00254
00255
00256 void UKMETIon::findPlace(const QString& place, const QString& source)
00257 {
00258 KUrl url;
00259 url = "http://www.bbc.co.uk/cgi-perl/weather/search/new_search.pl?x=0&y=0&=Submit&search_query=" + place + "&tmpl=wap";
00260
00261 d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
00262 d->m_job->addMetaData("cookies", "none");
00263 d->m_jobXml.insert(d->m_job, new QXmlStreamReader);
00264 d->m_jobList.insert(d->m_job, source);
00265
00266 if (d->m_job) {
00267 connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00268 SLOT(setup_slotDataArrived(KIO::Job *, const QByteArray &)));
00269 connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(setup_slotJobFinished(KJob *)));
00270
00271
00272 connect(d->m_job, SIGNAL(redirection(KIO::Job *, const KUrl &)), this,
00273 SLOT(setup_slotRedirected(KIO::Job *, const KUrl &)));
00274 }
00275 }
00276
00277 void UKMETIon::getFiveDayForecast(const QString& source)
00278 {
00279 KUrl url;
00280 url = d->m_place[source].XMLforecastURL;
00281 QString xmlMap = d->m_place[source].XMLforecastURL;
00282 xmlMap.replace("weather/5day.shtml", "weather/mobile/5day.wml");
00283 url = xmlMap;
00284
00285 d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
00286 d->m_job->addMetaData("cookies", "none");
00287 d->m_forecastJobXml.insert(d->m_job, new QXmlStreamReader);
00288 d->m_forecastJobList.insert(d->m_job, source);
00289
00290 if (d->m_job) {
00291 connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00292 SLOT(forecast_slotDataArrived(KIO::Job *, const QByteArray &)));
00293 connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(forecast_slotJobFinished(KJob *)));
00294 }
00295 }
00296
00297 bool UKMETIon::readSearchXMLData(const QString& key, QXmlStreamReader& xml)
00298 {
00299
00300 while (!xml.atEnd()) {
00301 xml.readNext();
00302
00303 if (xml.isEndElement()) {
00304 break;
00305 }
00306
00307 if (xml.isStartElement()) {
00308 if (xml.name() == "wml") {
00309 parseSearchLocations(key, xml);
00310 } else {
00311 parseUnknownElement(xml);
00312 }
00313 }
00314 }
00315
00316 return !xml.error();
00317 }
00318
00319 void UKMETIon::parseSearchLocations(const QString& source, QXmlStreamReader& xml)
00320 {
00321 int flag = 0;
00322 QString url;
00323 QString place;
00324 QStringList tokens;
00325 QString tmp;
00326 int counter = 2;
00327 int currentParagraph = 0;
00328
00329 Q_ASSERT(xml.isStartElement() && xml.name() == "wml");
00330
00331 while (!xml.atEnd()) {
00332 xml.readNext();
00333
00334 if (xml.isEndElement() && xml.name() == "wml") {
00335 break;
00336 }
00337
00338 if (xml.isStartElement() && xml.name() == "p") {
00339 currentParagraph++;
00340 }
00341
00342 if (currentParagraph == 2) {
00343 if (xml.isCharacters() && !xml.isWhitespace()) {
00344 QString dataText = xml.text().toString().trimmed();
00345 if (dataText.contains("No locations")) {
00346 break;
00347 }
00348 }
00349 }
00350
00351 if (xml.isStartElement()) {
00352 if (xml.name() == "a" && !xml.attributes().value("href").isEmpty()) {
00353 if (xml.attributes().value("href").toString().contains("5day.wml")) {
00354
00355
00356 tokens = xml.attributes().value("href").toString().split('=');
00357 if (xml.attributes().value("href").toString().contains("world")) {
00358 url = "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens[1] + ".xml";
00359 flag = 0;
00360 } else {
00361 url = "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens[1] + ".xml";
00362 flag = 1;
00363 }
00364 place = xml.readElementText();
00365 tmp = QString("bbcukmet|%1").arg(place);
00366
00367
00368 if (d->m_locations.contains(tmp)) {
00369
00370 QString dupePlace = place;
00371 tmp = QString("bbcukmet|%1").arg(QString("%1 (#%2)").arg(dupePlace).arg(counter));
00372 place = QString("%1 (#%2)").arg(dupePlace).arg(counter);
00373 counter++;
00374 }
00375
00376 if (flag) {
00377 d->m_place[tmp].XMLurl = url;
00378 d->m_place[tmp].place = place;
00379 d->m_place[tmp].ukPlace = true;
00380 } else {
00381 d->m_place[tmp].XMLurl = url;
00382 d->m_place[tmp].place = place;
00383 d->m_place[tmp].ukPlace = false;
00384 }
00385 d->m_locations.append(tmp);
00386 }
00387 }
00388 }
00389 }
00390 validate(source);
00391 }
00392
00393
00394 void UKMETIon::parseUnknownElement(QXmlStreamReader& xml)
00395 {
00396 while (!xml.atEnd()) {
00397 xml.readNext();
00398
00399 if (xml.isEndElement()) {
00400 break;
00401 }
00402
00403 if (xml.isStartElement()) {
00404 parseUnknownElement(xml);
00405 }
00406 }
00407 }
00408
00409 void UKMETIon::setup_slotRedirected(KIO::Job *job, const KUrl &url)
00410 {
00411 QString obsUrl;
00412 QString place;
00413 QString tmp;
00414 bool flag = false;
00415 QStringList tokens = url.url().split('=');
00416 if (url.url().contains("xhtml")) {
00417 if (url.url().contains("world")) {
00418 obsUrl = "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens[2] + ".xml";
00419 flag = false;
00420 } else {
00421 obsUrl = "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens[2] + ".xml";
00422 flag = true;
00423 }
00424 place = d->m_jobList[job].split('|')[2];
00425 tmp = QString("bbcukmet|%1").arg(place);
00426 place[0] = place[0].toUpper();
00427
00428 if (flag) {
00429 d->m_place[tmp].XMLurl = obsUrl;
00430 d->m_place[tmp].place = place;
00431 d->m_place[tmp].ukPlace = true;
00432 } else {
00433 d->m_place[tmp].XMLurl = obsUrl;
00434 d->m_place[tmp].place = place;
00435 d->m_place[tmp].ukPlace = false;
00436 }
00437 d->m_locations.append(tmp);
00438 validate(d->m_jobList[job]);
00439 }
00440 }
00441
00442 void UKMETIon::setup_slotDataArrived(KIO::Job *job, const QByteArray &data)
00443 {
00444 QByteArray local = data;
00445 if (data.isEmpty() || !d->m_jobXml.contains(job)) {
00446 return;
00447 }
00448
00449
00450 if (local.startsWith("<?xml version")) {
00451 local.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
00452 }
00453
00454
00455 d->m_jobXml[job]->addData(local);
00456 }
00457
00458 void UKMETIon::setup_slotJobFinished(KJob *job)
00459 {
00460 if (job->error() == 149) {
00461 setData(d->m_jobList[job], "validate", QString("bbcukmet|timeout"));
00462 disconnectSource(d->m_jobList[job], this);
00463 d->m_jobList.remove(job);
00464 delete d->m_jobXml[job];
00465 d->m_jobXml.remove(job);
00466 return;
00467 }
00468
00469 if (!d->m_locations.contains(QString("bbcukmet|%1").arg(d->m_jobList[job]))) {
00470 readSearchXMLData(d->m_jobList[job], *d->m_jobXml[job]);
00471 }
00472 d->m_jobList.remove(job);
00473 delete d->m_jobXml[job];
00474 d->m_jobXml.remove(job);
00475 }
00476
00477 void UKMETIon::observation_slotDataArrived(KIO::Job *job, const QByteArray &data)
00478 {
00479 QByteArray local = data;
00480 if (data.isEmpty() || !d->m_obsJobXml.contains(job)) {
00481 return;
00482 }
00483
00484
00485
00486 if (local.startsWith("<?xml version")) {
00487 local.replace("encoding=\"UTF-8\"?>", "encoding=\"cp1252\" ?>");
00488 }
00489
00490
00491 d->m_obsJobXml[job]->addData(local);
00492 }
00493
00494 void UKMETIon::observation_slotJobFinished(KJob *job)
00495 {
00496 setData(d->m_obsJobList[job], Data());
00497 readObservationXMLData(d->m_obsJobList[job], *d->m_obsJobXml[job]);
00498 d->m_obsJobList.remove(job);
00499 delete d->m_obsJobXml[job];
00500 d->m_obsJobXml.remove(job);
00501 }
00502
00503 void UKMETIon::forecast_slotDataArrived(KIO::Job *job, const QByteArray &data)
00504 {
00505 QByteArray local = data;
00506 if (data.isEmpty() || !d->m_forecastJobXml.contains(job)) {
00507 return;
00508 }
00509
00510
00511
00512 if (local.startsWith("<?xml version")) {
00513 local.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
00514 }
00515
00516 d->m_forecastJobXml[job]->addData(local);
00517 }
00518
00519 void UKMETIon::forecast_slotJobFinished(KJob *job)
00520 {
00521 setData(d->m_forecastJobList[job], Data());
00522 readFiveDayForecastXMLData(d->m_forecastJobList[job], *d->m_forecastJobXml[job]);
00523 d->m_forecastJobList.remove(job);
00524 delete d->m_forecastJobXml[job];
00525 d->m_forecastJobXml.remove(job);
00526 }
00527
00528 void UKMETIon::parsePlaceObservation(const QString &source, WeatherData& data, QXmlStreamReader& xml)
00529 {
00530 Q_ASSERT(xml.isStartElement() && xml.name() == "rss");
00531
00532 while (!xml.atEnd()) {
00533 xml.readNext();
00534
00535 if (xml.isEndElement() && xml.name() == "rss") {
00536 break;
00537 }
00538
00539 if (xml.isStartElement()) {
00540 if (xml.name() == "channel") {
00541 parseWeatherChannel(source, data, xml);
00542 }
00543 }
00544 }
00545 }
00546
00547 void UKMETIon::parseWeatherChannel(const QString& source, WeatherData& data, QXmlStreamReader& xml)
00548 {
00549 Q_ASSERT(xml.isStartElement() && xml.name() == "channel");
00550
00551 while (!xml.atEnd()) {
00552 xml.readNext();
00553
00554 if (xml.isEndElement() && xml.name() == "channel") {
00555 break;
00556 }
00557
00558 if (xml.isStartElement()) {
00559 if (xml.name() == "title") {
00560 data.stationName = xml.readElementText().split("Observations for")[1].trimmed();
00561
00562 data.stationName.replace("United Kingdom", "UK");
00563 data.stationName.replace("United States of America", "USA");
00564
00565 } else if (xml.name() == "item") {
00566 parseWeatherObservation(source, data, xml);
00567 } else {
00568 parseUnknownElement(xml);
00569 }
00570 }
00571 }
00572 }
00573
00574 void UKMETIon::parseWeatherObservation(const QString& source, WeatherData& data, QXmlStreamReader& xml)
00575 {
00576 Q_UNUSED(data)
00577 Q_ASSERT(xml.isStartElement() && xml.name() == "item");
00578
00579 while (!xml.atEnd()) {
00580 xml.readNext();
00581
00582 if (xml.isEndElement() && xml.name() == "item") {
00583 break;
00584 }
00585
00586 if (xml.isStartElement()) {
00587 if (xml.name() == "title") {
00588 QString conditionString = xml.readElementText();
00589
00590
00591 QStringList conditionData = conditionString.split(':');
00592
00593 data.obsTime = conditionData[0];
00594
00595 d->m_dateFormat = QDateTime::fromString(data.obsTime.split("at")[1].trimmed(), "hhmm 'GMT'");
00596 data.iconPeriodHour = d->m_dateFormat.toString("HH").toInt();
00597
00598
00599 data.condition = conditionData[1].split('.')[0].trimmed();
00600
00601 } else if (xml.name() == "link") {
00602 d->m_place[source].XMLforecastURL = xml.readElementText();
00603 } else if (xml.name() == "description") {
00604 QString observeString = xml.readElementText();
00605 QStringList observeData = observeString.split(':');
00606
00607 data.temperature_C = observeData[1].split(QChar(176))[0].trimmed();
00608 data.temperature_F = observeData[1].split('(')[1].split(QChar(176))[0];
00609
00610 data.windDirection = observeData[2].split(',')[0].trimmed();
00611 data.windSpeed_miles = observeData[3].split(',')[0].split(' ')[1];
00612
00613 data.humidity = observeData[4].split(',')[0].split(' ')[1];
00614
00615 data.pressure = observeData[5].split(',')[0].split(' ')[1].split("mB")[0];
00616
00617 data.pressureTendency = observeData[5].split(',')[1].trimmed();
00618
00619 data.visibilityStr = observeData[6].trimmed();
00620
00621 } else {
00622 parseUnknownElement(xml);
00623 }
00624 }
00625 }
00626 }
00627
00628 bool UKMETIon::readObservationXMLData(const QString& source, QXmlStreamReader& xml)
00629 {
00630 WeatherData data;
00631
00632 while (!xml.atEnd()) {
00633 xml.readNext();
00634
00635 if (xml.isEndElement()) {
00636 break;
00637 }
00638
00639 if (xml.isStartElement()) {
00640 if (xml.name() == "rss") {
00641 parsePlaceObservation(source, data, xml);
00642 } else {
00643 parseUnknownElement(xml);
00644 }
00645 }
00646
00647 }
00648
00649 d->m_weatherData[source] = data;
00650
00651
00652 getFiveDayForecast(source);
00653
00654 return !xml.error();
00655 }
00656
00657 bool UKMETIon::readFiveDayForecastXMLData(const QString& source, QXmlStreamReader& xml)
00658 {
00659 while (!xml.atEnd()) {
00660 xml.readNext();
00661
00662 if (xml.isEndElement()) {
00663 break;
00664 }
00665
00666 if (xml.isStartElement()) {
00667 if (xml.name() == "wml") {
00668 parseFiveDayForecast(source, xml);
00669 } else {
00670 parseUnknownElement(xml);
00671 }
00672 }
00673 }
00674 updateWeather(source);
00675 return !xml.error();
00676 }
00677
00678 void UKMETIon::parseFiveDayForecast(const QString& source, QXmlStreamReader& xml)
00679 {
00680 Q_ASSERT(xml.isStartElement() && xml.name() == "wml");
00681 bool validNumber = false;
00682 int currentParagraph = 0;
00683 bool skipPlace = false;
00684 int dataItem = 0;
00685
00686 enum DataItem {
00687 Day,
00688 Summary,
00689 MaxTemp,
00690 MinTemp,
00691 WindSpeed
00692 };
00693
00694
00695 d->m_weatherData[source].forecasts.clear();
00696
00697 WeatherData::ForecastInfo *forecast = new WeatherData::ForecastInfo;
00698
00699 QRegExp numParser("(Max|Min|Wind)\\s+-*([0-9]+)");
00700 while (!xml.atEnd()) {
00701 xml.readNext();
00702
00703 if (xml.isStartElement() && xml.name() == "p") {
00704 currentParagraph++;
00705 }
00706
00707 if (currentParagraph == 3) {
00708 if (xml.isCharacters() && !xml.isWhitespace()) {
00709 QString dataText = xml.text().toString().trimmed();
00710 if (!skipPlace) {
00711 skipPlace = true;
00712 } else {
00713 if (numParser.indexIn(dataText) != -1 && numParser.capturedTexts().count() >= 3) {
00714 validNumber = true;
00715 }
00716 switch (dataItem) {
00717 case Day:
00718 forecast->period = dataText;
00719 dataItem++;
00720 break;
00721 case Summary:
00722 forecast->summary = dataText;
00723 forecast->iconName = getWeatherIcon(dayIcons(), forecast->summary.toLower());
00724 dataItem++;
00725 break;
00726 case MaxTemp:
00727 forecast->tempHigh = numParser.capturedTexts()[0].remove("Max").toInt();
00728 dataItem++;
00729 validNumber = false;
00730 break;
00731 case MinTemp:
00732 forecast->tempLow = numParser.capturedTexts()[0].remove("Min").toInt();
00733 dataItem++;
00734 validNumber = false;
00735 break;
00736 case WindSpeed:
00737 forecast->windSpeed = numParser.capturedTexts()[0].remove("Wind").toInt();
00738 forecast->windDirection = dataText.split('(')[1].split(')')[0];
00739 dataItem = 0;
00740 d->m_weatherData[source].forecasts.append(forecast);
00741 forecast = new WeatherData::ForecastInfo;
00742 validNumber = false;
00743 break;
00744 };
00745 }
00746 }
00747 }
00748 }
00749
00750 delete forecast;
00751 }
00752
00753 void UKMETIon::validate(const QString& source)
00754 {
00755 bool beginflag = true;
00756
00757 if (!d->m_locations.count()) {
00758 QStringList invalidPlace = source.split('|');
00759 if (d->m_place[QString("bbcukmet|%1").arg(invalidPlace[2])].place.isEmpty()) {
00760 setData(source, "validate", QString("bbcukmet|invalid|multiple|%1").arg(invalidPlace[2]));
00761 }
00762 d->m_locations.clear();
00763 return;
00764 } else {
00765 QString placeList;
00766 foreach(const QString &place, d->m_locations) {
00767 if (beginflag) {
00768 placeList.append(QString("%1|extra|%2").arg(place.split('|')[1]).arg(d->m_place[place].XMLurl));
00769 beginflag = false;
00770 } else {
00771 placeList.append(QString("|place|%1|extra|%2").arg(place.split('|')[1]).arg(d->m_place[place].XMLurl));
00772 }
00773 }
00774 if (d->m_locations.count() > 1) {
00775 setData(source, "validate", QString("bbcukmet|valid|multiple|place|%1").arg(placeList));
00776 } else {
00777 placeList[0] = placeList[0].toUpper();
00778 setData(source, "validate", QString("bbcukmet|valid|single|place|%1").arg(placeList));
00779 }
00780 }
00781 d->m_locations.clear();
00782 }
00783
00784 void UKMETIon::updateWeather(const QString& source)
00785 {
00786 QString weatherSource = source;
00787 weatherSource.replace("bbcukmet|", "bbcukmet|weather|");
00788 weatherSource.append(QString("|%1").arg(d->m_place[source].XMLurl));
00789
00790 QMap<QString, QString> dataFields;
00791 QStringList fieldList;
00792 QVector<QString> forecastList;
00793 int i = 0;
00794
00795 setData(weatherSource, "Place", place(source));
00796 setData(weatherSource, "Station", station(source));
00797 setData(weatherSource, "Observation Period", observationTime(source));
00798 setData(weatherSource, "Current Conditions", condition(source));
00799
00800
00801 if (periodHour(source) >= 0 && periodHour(source) < 6) {
00802 setData(weatherSource, "Condition Icon", getWeatherIcon(nightIcons(), condition(source)));
00803 } else if (periodHour(source) >= 18) {
00804 setData(weatherSource, "Condition Icon", getWeatherIcon(nightIcons(), condition(source)));
00805 } else {
00806 setData(weatherSource, "Condition Icon", getWeatherIcon(dayIcons(), condition(source)));
00807 }
00808
00809 setData(weatherSource, "Humidity", humidity(source));
00810 setData(weatherSource, "Visibility", visibility(source));
00811
00812 dataFields = temperature(source);
00813 setData(weatherSource, "Temperature", dataFields["temperature"]);
00814 setData(weatherSource, "Temperature Unit", dataFields["temperatureUnit"]);
00815
00816 dataFields = pressure(source);
00817 setData(weatherSource, "Pressure", dataFields["pressure"]);
00818 setData(weatherSource, "Pressure Unit", dataFields["pressureUnit"]);
00819 setData(weatherSource, "Pressure Tendency", dataFields["pressureTendency"]);
00820
00821 dataFields = wind(source);
00822 setData(weatherSource, "Wind Speed", dataFields["windSpeed"]);
00823 setData(weatherSource, "Wind Speed Unit", dataFields["windUnit"]);
00824 setData(weatherSource, "Wind Direction", dataFields["windDirection"]);
00825
00826
00827 forecastList = forecasts(source);
00828
00829
00830 setData(weatherSource, QString("Total Weather Days"), d->m_weatherData[source].forecasts.size());
00831
00832 foreach(const QString &forecastItem, forecastList) {
00833 fieldList = forecastItem.split('|');
00834
00835 setData(weatherSource, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6") \
00836 .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[2]).arg(fieldList[3]) \
00837 .arg(fieldList[4]).arg(fieldList[5]));
00838 i++;
00839 }
00840
00841 setData(weatherSource, "Credit", "Supported by backstage.bbc.co.uk / Data from UK MET Office");
00842 setData(weatherSource, "Credit Url", d->m_place[source].XMLforecastURL);
00843 }
00844
00845 QString UKMETIon::place(const QString& source)
00846 {
00847 return d->m_weatherData[source].stationName;
00848 }
00849
00850 QString UKMETIon::station(const QString& source)
00851 {
00852 return d->m_weatherData[source].stationName;
00853 }
00854
00855 QString UKMETIon::observationTime(const QString& source)
00856 {
00857 return d->m_weatherData[source].obsTime;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 int UKMETIon::periodHour(const QString& source)
00870 {
00871 return d->m_weatherData[source].iconPeriodHour;
00872 }
00873
00874 QString UKMETIon::condition(const QString& source)
00875 {
00876 return d->m_weatherData[source].condition;
00877 }
00878
00879 QMap<QString, QString> UKMETIon::temperature(const QString& source)
00880 {
00881 QMap<QString, QString> temperatureInfo;
00882
00883 temperatureInfo.insert("temperature", QString(d->m_weatherData[source].temperature_C));
00884 temperatureInfo.insert("temperatureUnit", QString::number(WeatherUtils::Celsius));
00885 return temperatureInfo;
00886 }
00887
00888 QMap<QString, QString> UKMETIon::wind(const QString& source)
00889 {
00890 QMap<QString, QString> windInfo;
00891 if (d->m_weatherData[source].windSpeed_miles == "N/A") {
00892 windInfo.insert("windSpeed", "N/A");
00893 windInfo.insert("windUnit", QString::number(WeatherUtils::NoUnit));
00894 } else {
00895 windInfo.insert("windSpeed", QString(d->m_weatherData[source].windSpeed_miles));
00896 windInfo.insert("windUnit", QString::number(WeatherUtils::MilesAnHour));
00897 }
00898 windInfo.insert("windDirection", d->m_weatherData[source].windDirection);
00899 return windInfo;
00900 }
00901
00902 QString UKMETIon::humidity(const QString& source)
00903 {
00904 if (d->m_weatherData[source].humidity == "N/A%") {
00905 return "N/A";
00906 }
00907 return d->m_weatherData[source].humidity;
00908 }
00909
00910 QString UKMETIon::visibility(const QString& source)
00911 {
00912 return d->m_weatherData[source].visibilityStr;
00913 }
00914
00915 QMap<QString, QString> UKMETIon::pressure(const QString& source)
00916 {
00917 QMap<QString, QString> pressureInfo;
00918 if (d->m_weatherData[source].pressure == "N/A") {
00919 pressureInfo.insert("pressure", "N/A");
00920 return pressureInfo;
00921 }
00922
00923 pressureInfo.insert("pressure", QString(d->m_weatherData[source].pressure));
00924 pressureInfo.insert("pressureUnit", QString::number(WeatherUtils::Millibars));
00925
00926 pressureInfo.insert("pressureTendency", d->m_weatherData[source].pressureTendency);
00927 return pressureInfo;
00928 }
00929
00930 QVector<QString> UKMETIon::forecasts(const QString& source)
00931 {
00932 QVector<QString> forecastData;
00933
00934 for (int i = 0; i < d->m_weatherData[source].forecasts.size(); ++i) {
00935
00936 if (d->m_weatherData[source].forecasts[i]->period.contains("Saturday")) {
00937 d->m_weatherData[source].forecasts[i]->period.replace("Saturday", "Sat");
00938 }
00939
00940 if (d->m_weatherData[source].forecasts[i]->period.contains("Sunday")) {
00941 d->m_weatherData[source].forecasts[i]->period.replace("Sunday", "Sun");
00942 }
00943
00944 if (d->m_weatherData[source].forecasts[i]->period.contains("Monday")) {
00945 d->m_weatherData[source].forecasts[i]->period.replace("Monday", "Mon");
00946 }
00947
00948 if (d->m_weatherData[source].forecasts[i]->period.contains("Tuesday")) {
00949 d->m_weatherData[source].forecasts[i]->period.replace("Tuesday", "Tue");
00950 }
00951
00952 if (d->m_weatherData[source].forecasts[i]->period.contains("Wednesday")) {
00953 d->m_weatherData[source].forecasts[i]->period.replace("Wednesday", "Wed");
00954 }
00955
00956 if (d->m_weatherData[source].forecasts[i]->period.contains("Thursday")) {
00957 d->m_weatherData[source].forecasts[i]->period.replace("Thursday", "Thu");
00958 }
00959 if (d->m_weatherData[source].forecasts[i]->period.contains("Friday")) {
00960 d->m_weatherData[source].forecasts[i]->period.replace("Friday", "Fri");
00961 }
00962
00963 forecastData.append(QString("%1|%2|%3|%4|%5|%6") \
00964 .arg(d->m_weatherData[source].forecasts[i]->period) \
00965 .arg(d->m_weatherData[source].forecasts[i]->iconName) \
00966 .arg(d->m_weatherData[source].forecasts[i]->summary) \
00967 .arg(d->m_weatherData[source].forecasts[i]->tempHigh) \
00968 .arg(d->m_weatherData[source].forecasts[i]->tempLow) \
00969 .arg("N/U"));
00970
00971
00972 }
00973
00974 return forecastData;
00975 }
00976
00977 #include "ion_bbcukmet.moc"