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
00682 int currentParagraph = 0;
00683 bool skipPlace = false;
00684 int dataItem = 0;
00685 int numberValue = 0;
00686
00687 enum DataItem {
00688 Day,
00689 Summary,
00690 MaxTemp,
00691 MinTemp,
00692 WindSpeed
00693 };
00694
00695
00696 d->m_weatherData[source].forecasts.clear();
00697
00698 WeatherData::ForecastInfo *forecast = new WeatherData::ForecastInfo;
00699
00700 QRegExp numParser("(Max|Min|Wind)\\s+-*([0-9]+)");
00701 while (!xml.atEnd()) {
00702 xml.readNext();
00703
00704 if (xml.isStartElement() && xml.name() == "p") {
00705 currentParagraph++;
00706 }
00707
00708 if (currentParagraph == 3) {
00709 if (xml.isCharacters() && !xml.isWhitespace()) {
00710 QString dataText = xml.text().toString().trimmed();
00711 if (!skipPlace) {
00712 skipPlace = true;
00713 } else {
00714 if (numParser.indexIn(dataText) != -1 && numParser.capturedTexts().count() >= 3) {
00715 numberValue = numParser.capturedTexts()[2].toInt();
00716 }
00717 switch (dataItem) {
00718 case Day:
00719 forecast->period = dataText;
00720 dataItem++;
00721 break;
00722 case Summary:
00723 forecast->summary = dataText;
00724 forecast->iconName = getWeatherIcon(dayIcons(), forecast->summary.toLower());
00725 dataItem++;
00726 break;
00727 case MaxTemp:
00728 forecast->tempHigh = numberValue;
00729 dataItem++;
00730 break;
00731 case MinTemp:
00732 forecast->tempLow = numberValue;
00733 dataItem++;
00734 break;
00735 case WindSpeed:
00736 forecast->windSpeed = numberValue;
00737 forecast->windDirection = dataText.split("(")[1].split(")")[0];
00738 dataItem = 0;
00739 d->m_weatherData[source].forecasts.append(forecast);
00740 forecast = new WeatherData::ForecastInfo;
00741 break;
00742 };
00743 }
00744 }
00745 }
00746 }
00747
00748 delete forecast;
00749 }
00750
00751 void UKMETIon::validate(const QString& source)
00752 {
00753 bool beginflag = true;
00754
00755 if (!d->m_locations.count()) {
00756 QStringList invalidPlace = source.split('|');
00757 if (d->m_place[QString("bbcukmet|%1").arg(invalidPlace[2])].place.isEmpty()) {
00758 setData(source, "validate", QString("bbcukmet|invalid|multiple|%1").arg(invalidPlace[2]));
00759 }
00760 d->m_locations.clear();
00761 return;
00762 } else {
00763 QString placeList;
00764 foreach(const QString &place, d->m_locations) {
00765 if (beginflag) {
00766 placeList.append(QString("%1|extra|%2").arg(place.split("|")[1]).arg(d->m_place[place].XMLurl));
00767 beginflag = false;
00768 } else {
00769 placeList.append(QString("|place|%1|extra|%2").arg(place.split("|")[1]).arg(d->m_place[place].XMLurl));
00770 }
00771 }
00772 if (d->m_locations.count() > 1) {
00773 setData(source, "validate", QString("bbcukmet|valid|multiple|place|%1").arg(placeList));
00774 } else {
00775 placeList[0] = placeList[0].toUpper();
00776 setData(source, "validate", QString("bbcukmet|valid|single|place|%1").arg(placeList));
00777 }
00778 }
00779 d->m_locations.clear();
00780 }
00781
00782 void UKMETIon::updateWeather(const QString& source)
00783 {
00784 QString weatherSource = source;
00785 weatherSource.replace("bbcukmet|", "bbcukmet|weather|");
00786 weatherSource.append(QString("|%1").arg(d->m_place[source].XMLurl));
00787
00788 QMap<QString, QString> dataFields;
00789 QStringList fieldList;
00790 QVector<QString> forecastList;
00791 int i = 0;
00792
00793 setData(weatherSource, "Place", place(source));
00794 setData(weatherSource, "Station", station(source));
00795 setData(weatherSource, "Observation Period", observationTime(source));
00796 setData(weatherSource, "Current Conditions", condition(source));
00797
00798
00799 if (periodHour(source) >= 0 && periodHour(source) < 6) {
00800 setData(weatherSource, "Condition Icon", getWeatherIcon(nightIcons(), condition(source)));
00801 } else if (periodHour(source) >= 18) {
00802 setData(weatherSource, "Condition Icon", getWeatherIcon(nightIcons(), condition(source)));
00803 } else {
00804 setData(weatherSource, "Condition Icon", getWeatherIcon(dayIcons(), condition(source)));
00805 }
00806
00807 setData(weatherSource, "Humidity", humidity(source));
00808 setData(weatherSource, "Visibility", visibility(source));
00809
00810 dataFields = temperature(source);
00811 setData(weatherSource, "Temperature", dataFields["temperature"]);
00812 setData(weatherSource, "Temperature Unit", dataFields["temperatureUnit"]);
00813
00814 dataFields = pressure(source);
00815 setData(weatherSource, "Pressure", dataFields["pressure"]);
00816 setData(weatherSource, "Pressure Unit", dataFields["pressureUnit"]);
00817 setData(weatherSource, "Pressure Tendency", dataFields["pressureTendency"]);
00818
00819 dataFields = wind(source);
00820 setData(weatherSource, "Wind Speed", dataFields["windSpeed"]);
00821 setData(weatherSource, "Wind Speed Unit", dataFields["windUnit"]);
00822 setData(weatherSource, "Wind Direction", dataFields["windDirection"]);
00823
00824
00825 forecastList = forecasts(source);
00826
00827
00828 setData(weatherSource, QString("Total Weather Days"), d->m_weatherData[source].forecasts.size());
00829
00830 foreach(const QString &forecastItem, forecastList) {
00831 fieldList = forecastItem.split('|');
00832
00833 setData(weatherSource, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6") \
00834 .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[2]).arg(fieldList[3]) \
00835 .arg(fieldList[4]).arg(fieldList[5]));
00836 i++;
00837 }
00838
00839 setData(weatherSource, "Credit", "Supported by backstage.bbc.co.uk / Data from UK MET Office");
00840 setData(weatherSource, "Credit Url", d->m_place[source].XMLforecastURL);
00841 }
00842
00843 QString UKMETIon::place(const QString& source)
00844 {
00845 return d->m_weatherData[source].stationName;
00846 }
00847
00848 QString UKMETIon::station(const QString& source)
00849 {
00850 return d->m_weatherData[source].stationName;
00851 }
00852
00853 QString UKMETIon::observationTime(const QString& source)
00854 {
00855 return d->m_weatherData[source].obsTime;
00856 }
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 int UKMETIon::periodHour(const QString& source)
00868 {
00869 return d->m_weatherData[source].iconPeriodHour;
00870 }
00871
00872 QString UKMETIon::condition(const QString& source)
00873 {
00874 return d->m_weatherData[source].condition;
00875 }
00876
00877 QMap<QString, QString> UKMETIon::temperature(const QString& source)
00878 {
00879 QMap<QString, QString> temperatureInfo;
00880
00881 temperatureInfo.insert("temperature", QString(d->m_weatherData[source].temperature_C));
00882 temperatureInfo.insert("temperatureUnit", QString::number(WeatherUtils::Celsius));
00883 return temperatureInfo;
00884 }
00885
00886 QMap<QString, QString> UKMETIon::wind(const QString& source)
00887 {
00888 QMap<QString, QString> windInfo;
00889 if (d->m_weatherData[source].windSpeed_miles == "N/A") {
00890 windInfo.insert("windSpeed", "N/A");
00891 windInfo.insert("windUnit", QString::number(WeatherUtils::NoUnit));
00892 } else {
00893 windInfo.insert("windSpeed", QString(d->m_weatherData[source].windSpeed_miles));
00894 windInfo.insert("windUnit", QString::number(WeatherUtils::MilesAnHour));
00895 }
00896 windInfo.insert("windDirection", d->m_weatherData[source].windDirection);
00897 return windInfo;
00898 }
00899
00900 QString UKMETIon::humidity(const QString& source)
00901 {
00902 if (d->m_weatherData[source].humidity == "N/A%") {
00903 return "N/A";
00904 }
00905 return d->m_weatherData[source].humidity;
00906 }
00907
00908 QString UKMETIon::visibility(const QString& source)
00909 {
00910 return d->m_weatherData[source].visibilityStr;
00911 }
00912
00913 QMap<QString, QString> UKMETIon::pressure(const QString& source)
00914 {
00915 QMap<QString, QString> pressureInfo;
00916 if (d->m_weatherData[source].pressure == "N/A") {
00917 pressureInfo.insert("pressure", "N/A");
00918 return pressureInfo;
00919 }
00920
00921 pressureInfo.insert("pressure", QString(d->m_weatherData[source].pressure));
00922 pressureInfo.insert("pressureUnit",