• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Engines

ion_bbcukmet.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by Shawn Starr <shawn.starr@rogers.com>            *
00003  *                                                                         *
00004  *   This program is free software; you can redistribute it and/or modify  *
00005  *   it under the terms of the GNU General Public License as published by  *
00006  *   the Free Software Foundation; either version 2 of the License, or     *
00007  *   (at your option) any later version.                                   *
00008  *                                                                         *
00009  *   This program is distributed in the hope that it will be useful,       *
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00012  *   GNU General Public License for more details.                          *
00013  *                                                                         *
00014  *   You should have received a copy of the GNU General Public License     *
00015  *   along with this program; if not, write to the                         *
00016  *   Free Software Foundation, Inc.,                                       *
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA          *
00018  ***************************************************************************/
00019 
00020 /* Ion for BBC's Weather from the UK Met Office */
00021 
00022 #include "ion_bbcukmet.h"
00023 
00024 class UKMETIon::Private : public QObject
00025 {
00026 public:
00027     Private() { m_url = 0;}
00028     ~Private() { delete m_url; }
00029 
00030 private:
00031     struct XMLMapInfo {
00032         QString place;
00033         QString XMLurl;
00034         QString XMLforecastURL;
00035         bool ukPlace;
00036         QString sourceOptions;
00037     };
00038 
00039 public:
00040     // Key dicts
00041     QHash<QString, UKMETIon::Private::XMLMapInfo> m_place;
00042     QVector<QString> m_locations;
00043     QStringList m_matchLocations;
00044     bool isValid;
00045 
00046 public:
00047     // Weather information
00048     QHash<QString, WeatherData> m_weatherData;
00049 
00050     // Store KIO jobs - Search list
00051     QMap<KJob *, QXmlStreamReader*> m_jobXml;
00052     QMap<KJob *, QString> m_jobList;
00053 
00054     QMap<KJob *, QXmlStreamReader*> m_obsJobXml;
00055     QMap<KJob *, QString> m_obsJobList;
00056 
00057     QMap<KJob *, QXmlStreamReader *> m_forecastJobXml;
00058     QMap<KJob *, QString> m_forecastJobList;
00059 
00060     KUrl *m_url;
00061     KIO::TransferJob *m_job;
00062 
00063     int m_timezoneType;  // Ion option: Timezone may be local time or UTC time
00064     int m_measureType; // Ion option: Units may be Metric or Imperial
00065 };
00066 
00067 
00068 // ctor, dtor
00069 UKMETIon::UKMETIon(QObject *parent, const QVariantList &args)
00070         : IonInterface(parent, args), d(new Private())
00071 
00072 {
00073     Q_UNUSED(args)
00074 }
00075 
00076 UKMETIon::~UKMETIon()
00077 {
00078     // Destroy each forecast stored in a QVector
00079     foreach(const WeatherData &item, d->m_weatherData) {
00080         foreach(WeatherData::ForecastInfo *forecast, item.forecasts) {
00081             if (forecast) {
00082                 delete forecast;
00083             }
00084         }
00085     }
00086 
00087     // Destroy dptr
00088     delete d;
00089 }
00090 
00091 // Get the master list of locations to be parsed
00092 void UKMETIon::init()
00093 {
00094     setInitialized(true);
00095 }
00096 
00097 // Get a specific Ion's data
00098 bool UKMETIon::updateIonSource(const QString& source)
00099 {
00100     // We expect the applet to send the source in the following tokenization:
00101     // ionname|validate|place_name - Triggers validation of place
00102     // ionname|weather|place_name - Triggers receiving weather of place
00103 
00104     QStringList sourceAction = source.split('|');
00105 
00106     if (sourceAction[1] == QString("validate")) {
00107         // Look for places to match
00108         findPlace(sourceAction[2], source);
00109         return true;
00110 
00111     } else if (sourceAction[1] == QString("weather")) {
00112         if (sourceAction.count() >= 3) {
00113             d->m_place[QString("bbcukmet|%1").arg(sourceAction[2])].XMLurl = sourceAction[3];
00114             getXMLData(QString("%1|%2").arg(sourceAction[0]).arg(sourceAction[2]));
00115             return true;
00116     } else { 
00117         return false;
00118     }
00119     }
00120     return false;
00121 }
00122 
00123 // Gets specific city XML data
00124 void UKMETIon::getXMLData(const QString& source)
00125 {
00126     KUrl url;
00127     url = d->m_place[source].XMLurl;
00128 
00129     d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
00130     d->m_job->addMetaData("cookies", "none"); // Disable displaying cookies
00131     d->m_obsJobXml.insert(d->m_job, new QXmlStreamReader);
00132     d->m_obsJobList.insert(d->m_job, source);
00133 
00134     if (d->m_job) {
00135         connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00136                 SLOT(observation_slotDataArrived(KIO::Job *, const QByteArray &)));
00137         connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(observation_slotJobFinished(KJob *)));
00138     }
00139 }
00140 
00141 // Parses city list and gets the correct city based on ID number
00142 void UKMETIon::findPlace(const QString& place, const QString& source)
00143 {
00144     KUrl url;
00145     url = "http://www.bbc.co.uk/cgi-perl/weather/search/new_search.pl?x=0&y=0&=Submit&search_query=" + place + "&tmpl=wap";
00146 
00147     d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
00148     d->m_job->addMetaData("cookies", "none"); // Disable displaying cookies
00149     d->m_jobXml.insert(d->m_job, new QXmlStreamReader);
00150     d->m_jobList.insert(d->m_job, source);
00151 
00152     if (d->m_job) {
00153         connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00154                 SLOT(setup_slotDataArrived(KIO::Job *, const QByteArray &)));
00155         connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(setup_slotJobFinished(KJob *)));
00156 
00157     // Handle redirects for direct hit places.
00158     connect(d->m_job, SIGNAL(redirection(KIO::Job *, const KUrl &)), this,
00159         SLOT(setup_slotRedirected(KIO::Job *, const KUrl &)));
00160     }
00161 }
00162 
00163 void UKMETIon::getFiveDayForecast(const QString& source)
00164 {
00165     KUrl url;
00166     url = d->m_place[source].XMLforecastURL.replace("weather/5day.shtml", "weather/mobile/5day.wml");
00167 
00168     d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
00169     d->m_job->addMetaData("cookies", "none"); // Disable displaying cookies
00170     d->m_forecastJobXml.insert(d->m_job, new QXmlStreamReader);
00171     d->m_forecastJobList.insert(d->m_job, source);
00172 
00173     if (d->m_job) {
00174         connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00175                 SLOT(forecast_slotDataArrived(KIO::Job *, const QByteArray &)));
00176         connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(forecast_slotJobFinished(KJob *)));
00177     }
00178 }
00179 
00180 bool UKMETIon::readSearchXMLData(const QString& key, QXmlStreamReader& xml)
00181 {
00182 
00183     while (!xml.atEnd()) {
00184         xml.readNext();
00185 
00186         if (xml.isEndElement()) {
00187             break;
00188         }
00189 
00190         if (xml.isStartElement()) {
00191             if (xml.name() == "wml") {
00192                 parseSearchLocations(key, xml);
00193             } else {
00194                 parseUnknownElement(xml);
00195             }
00196         }
00197     }
00198 
00199     return !xml.error();
00200 }
00201 
00202 void UKMETIon::parseSearchLocations(const QString& source, QXmlStreamReader& xml)
00203 {
00204     int flag = 0;
00205     QString url;
00206     QString place;
00207     QStringList tokens;
00208     QString tmp;
00209     int counter = 2;
00210     int currentParagraph = 0;
00211 
00212     Q_ASSERT(xml.isStartElement() && xml.name() == "wml");
00213 
00214     while (!xml.atEnd()) {
00215         xml.readNext();
00216 
00217         if (xml.isEndElement() && xml.name() == "wml") {
00218             break;
00219         }
00220 
00221         if (xml.isStartElement() && xml.name() == "p") {
00222             currentParagraph++;
00223         }
00224 
00225         if (currentParagraph == 2) {
00226            if (xml.isCharacters() && !xml.isWhitespace())  {
00227            QString dataText = xml.text().toString().trimmed();
00228            if (dataText.contains("No locations")) {
00229            break;
00230            }
00231        }
00232         }
00233 
00234         if (xml.isStartElement()) {
00235             if (xml.name() == "a" && !xml.attributes().value("href").isEmpty()) {
00236                 if (xml.attributes().value("href").toString().contains("5day.wml")) {
00237 
00238                     // Split URL to determine station ID number
00239                     tokens = xml.attributes().value("href").toString().split("=");
00240                     if (xml.attributes().value("href").toString().contains("world")) {
00241                         url = "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens[1] + ".xml";
00242                         flag = 0;
00243                     } else {
00244                         url = "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens[1] + ".xml";
00245                         flag = 1;
00246                     }
00247                     place = xml.readElementText();
00248                     tmp = QString("bbcukmet|%1").arg(place);
00249 
00250                     // Duplicate places can exist
00251                     if (d->m_locations.contains(tmp)) {
00252 
00253                         QString dupePlace = place;
00254                         tmp = QString("bbcukmet|%1").arg(QString("%1 (#%2)").arg(dupePlace).arg(counter));
00255                         place = QString("%1 (#%2)").arg(dupePlace).arg(counter);
00256                         counter++;
00257                     }
00258 
00259                     if (flag) {  // This is a UK specific location
00260                         d->m_place[tmp].XMLurl = url;
00261                         d->m_place[tmp].place = place;
00262                         d->m_place[tmp].ukPlace = true;
00263                     } else {
00264                         d->m_place[tmp].XMLurl = url;
00265                         d->m_place[tmp].place = place;
00266                         d->m_place[tmp].ukPlace = false;
00267                     }
00268                     d->m_locations.append(tmp);
00269                 } 
00270             }
00271         }
00272     }
00273     validate(source);
00274 }
00275 
00276 // handle when no XML tag is found
00277 void UKMETIon::parseUnknownElement(QXmlStreamReader& xml)
00278 {
00279     while (!xml.atEnd()) {
00280         xml.readNext();
00281 
00282         if (xml.isEndElement()) {
00283             break;
00284         }
00285 
00286         if (xml.isStartElement()) {
00287             parseUnknownElement(xml);
00288         }
00289     }
00290 }
00291 
00292 void UKMETIon::setup_slotRedirected(KIO::Job *job, const KUrl &url)
00293 {
00294     QString obsUrl;
00295     QString place;
00296     QString tmp;
00297     bool flag = false;
00298     QStringList tokens = url.url().split("=");
00299     if (url.url().contains("xhtml")) { // We don't care about the first redirection (there is two)
00300         if (url.url().contains("world")) {
00301         obsUrl = "http://feeds.bbc.co.uk/weather/feeds/obs/world/" + tokens[2] + ".xml";
00302         flag = false;
00303     } else {
00304         obsUrl = "http://feeds.bbc.co.uk/weather/feeds/obs/id/" + tokens[2] + ".xml";
00305         flag = true;
00306     }
00307     place = d->m_jobList[job].split("|")[2]; // Contains the source name (place in this case)
00308     tmp = QString("bbcukmet|%1").arg(place);
00309     place[0] = place[0].toUpper();
00310 
00311     if (flag) { // This is a UK specific location
00312         d->m_place[tmp].XMLurl = obsUrl;
00313         d->m_place[tmp].place = place;
00314         d->m_place[tmp].ukPlace = true;
00315     } else {
00316         d->m_place[tmp].XMLurl = obsUrl;
00317         d->m_place[tmp].place = place;
00318         d->m_place[tmp].ukPlace = false;
00319     }
00320     d->m_locations.append(tmp);
00321         validate(d->m_jobList[job]);
00322     }
00323 }
00324 
00325 void UKMETIon::setup_slotDataArrived(KIO::Job *job, const QByteArray &data)
00326 {
00327     QByteArray local = data;
00328     if (data.isEmpty() || !d->m_jobXml.contains(job)) {
00329         return;
00330     }
00331 
00332     // XXX: BBC doesn't convert unicode strings so this breaks XML formatting. Not pretty.
00333     if (local.startsWith("<?xml version")) {
00334         local.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
00335     }
00336 
00337     // Send to xml.
00338     d->m_jobXml[job]->addData(local);
00339 }
00340 
00341 void UKMETIon::setup_slotJobFinished(KJob *job)
00342 {
00343     if (job->error() == 149) {
00344         setData(d->m_jobList[job], "validate", QString("bbcukmet|timeout"));
00345         disconnectSource(d->m_jobList[job], this);
00346         d->m_jobList.remove(job);
00347         delete d->m_jobXml[job];
00348         d->m_jobXml.remove(job);
00349         return;
00350     }
00351     // If Redirected, don't go to this routine
00352     if (!d->m_locations.contains(QString("bbcukmet|%1").arg(d->m_jobList[job]))) {
00353         readSearchXMLData(d->m_jobList[job], *d->m_jobXml[job]);
00354     }
00355     d->m_jobList.remove(job);
00356     delete d->m_jobXml[job];
00357     d->m_jobXml.remove(job);
00358 }
00359 
00360 void UKMETIon::observation_slotDataArrived(KIO::Job *job, const QByteArray &data)
00361 {
00362     QByteArray local = data;
00363     if (data.isEmpty() || !d->m_obsJobXml.contains(job)) {
00364         return;
00365     }
00366 
00367     // XXX: I don't know what to say about this. But horrible. We can't really do much about this :/
00368     // No, it's not UTF-8, it really lies.
00369     if (local.startsWith("<?xml version")) {
00370         local.replace("encoding=\"UTF-8\"?>", "encoding=\"cp1252\" ?>");
00371     }
00372 
00373     // Send to xml.
00374     d->m_obsJobXml[job]->addData(local);
00375 }
00376 
00377 void UKMETIon::observation_slotJobFinished(KJob *job)
00378 {
00379     setData(d->m_obsJobList[job], Data());
00380     readObservationXMLData(d->m_obsJobList[job], *d->m_obsJobXml[job]);
00381     d->m_obsJobList.remove(job);
00382     delete d->m_obsJobXml[job];
00383     d->m_obsJobXml.remove(job);
00384 }
00385 
00386 void UKMETIon::forecast_slotDataArrived(KIO::Job *job, const QByteArray &data)
00387 {
00388     QByteArray local = data;
00389     if (data.isEmpty() || !d->m_forecastJobXml.contains(job)) {
00390         return;
00391     }
00392 
00393     // XXX: BBC doesn't convert unicode strings so this breaks XML formatting. Not pretty.
00394     // No, it's not UTF-8, it really lies.
00395     if (local.startsWith("<?xml version")) {
00396         local.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"cp1252\" ?>");
00397     }
00398     // Send to xml.
00399     d->m_forecastJobXml[job]->addData(local);
00400 }
00401 
00402 void UKMETIon::forecast_slotJobFinished(KJob *job)
00403 {
00404     setData(d->m_forecastJobList[job], Data());
00405     readFiveDayForecastXMLData(d->m_forecastJobList[job], *d->m_forecastJobXml[job]);
00406     d->m_forecastJobList.remove(job);
00407     delete d->m_forecastJobXml[job];
00408     d->m_forecastJobXml.remove(job);
00409 }
00410 
00411 void UKMETIon::parsePlaceObservation(const QString &source, WeatherData& data, QXmlStreamReader& xml)
00412 {
00413     Q_ASSERT(xml.isStartElement() && xml.name() == "rss");
00414 
00415     while (!xml.atEnd()) {
00416         xml.readNext();
00417 
00418         if (xml.isEndElement() && xml.name() == "rss") {
00419             break;
00420         }
00421 
00422         if (xml.isStartElement()) {
00423             if (xml.name() == "channel") {
00424                 parseWeatherChannel(source, data, xml);
00425             }
00426         }
00427     }
00428 }
00429 
00430 void UKMETIon::parseWeatherChannel(const QString& source, WeatherData& data, QXmlStreamReader& xml)
00431 {
00432     Q_ASSERT(xml.isStartElement() && xml.name() == "channel");
00433 
00434     while (!xml.atEnd()) {
00435         xml.readNext();
00436 
00437         if (xml.isEndElement() && xml.name() == "channel") {
00438             break;
00439         }
00440 
00441         if (xml.isStartElement()) {
00442             if (xml.name() == "title") {
00443                 data.stationName = xml.readElementText().split("Observations for")[1].trimmed();
00444             } else if (xml.name() == "item") {
00445                 parseWeatherObservation(source, data, xml);
00446             } else {
00447                 parseUnknownElement(xml);
00448             }
00449         }
00450     }
00451 }
00452 
00453 void UKMETIon::parseWeatherObservation(const QString& source, WeatherData& data, QXmlStreamReader& xml)
00454 {
00455     Q_UNUSED(data)
00456     Q_ASSERT(xml.isStartElement() && xml.name() == "item");
00457 
00458     while (!xml.atEnd()) {
00459         xml.readNext();
00460 
00461         if (xml.isEndElement() && xml.name() == "item") {
00462             break;
00463         }
00464 
00465         if (xml.isStartElement()) {
00466             if (xml.name() == "title") {
00467                 QString conditionString = xml.readElementText();
00468 
00469                 // Get the observation time.
00470                 QStringList conditionData = conditionString.split(":");
00471 
00472                 data.obsTime = conditionData[0];
00473                 data.condition = conditionData[1].split(".")[0].trimmed();
00474             } else if (xml.name() == "link") {
00475                 d->m_place[source].XMLforecastURL = xml.readElementText();
00476             } else if (xml.name() == "description") {
00477                 QString observeString = xml.readElementText();
00478                 QStringList observeData = observeString.split(":");
00479 
00480                 data.temperature_C = observeData[1].split(QChar(176))[0].trimmed();
00481                 data.temperature_F = observeData[1].split("(")[1].split(QChar(176))[0];
00482 
00483                 data.windDirection = observeData[2].split(",")[0].trimmed();
00484                 data.windSpeed_miles = observeData[3].split(",")[0].split(" ")[1];
00485 
00486                 data.humidity = observeData[4].split(",")[0].split(" ")[1];
00487 
00488                 data.pressure = observeData[5].split(",")[0].split(" ")[1].split("mB")[0];
00489 
00490                 data.pressureTendency = observeData[5].split(",")[1].trimmed();
00491 
00492                 data.visibilityStr = observeData[6].trimmed();
00493 
00494             } else {
00495                 parseUnknownElement(xml);
00496             }
00497         }
00498     }
00499 }
00500 
00501 bool UKMETIon::readObservationXMLData(const QString& source, QXmlStreamReader& xml)
00502 {
00503     WeatherData data;
00504 
00505     while (!xml.atEnd()) {
00506         xml.readNext();
00507 
00508         if (xml.isEndElement()) {
00509             break;
00510         }
00511 
00512         if (xml.isStartElement()) {
00513             if (xml.name() == "rss") {
00514                 parsePlaceObservation(source, data, xml);
00515             } else {
00516                 parseUnknownElement(xml);
00517             }
00518         }
00519 
00520     }
00521 
00522     d->m_weatherData[source] = data;
00523 
00524     // Get the 5 day forecast info next.
00525     getFiveDayForecast(source);
00526 
00527     return !xml.error();
00528 }
00529 
00530 bool UKMETIon::readFiveDayForecastXMLData(const QString& source, QXmlStreamReader& xml)
00531 {
00532     while (!xml.atEnd()) {
00533         xml.readNext();
00534 
00535         if (xml.isEndElement()) {
00536             break;
00537         }
00538 
00539         if (xml.isStartElement()) {
00540             if (xml.name() == "wml") {
00541                 parseFiveDayForecast(source, xml);
00542             } else {
00543                 parseUnknownElement(xml);
00544             }
00545         }
00546     }
00547     updateWeather(source);
00548     return !xml.error();
00549 }
00550 
00551 void UKMETIon::parseFiveDayForecast(const QString& source, QXmlStreamReader& xml)
00552 {
00553     Q_ASSERT(xml.isStartElement() && xml.name() == "wml");
00554 
00555     int currentParagraph = 0;
00556     bool skipPlace = false;
00557     int dataItem = 0;
00558     int numberValue = 0;
00559 
00560     enum DataItem {
00561         Day,
00562         Summary,
00563         MaxTemp,
00564         MinTemp,
00565         WindSpeed
00566     };
00567 
00568     // Flush out the old forecasts when updating.
00569     d->m_weatherData[source].forecasts.clear();
00570 
00571     WeatherData::ForecastInfo *forecast = new WeatherData::ForecastInfo;
00572 
00573     QRegExp numParser("(Max|Min|Wind)\\s+-*([0-9]+)");
00574     while (!xml.atEnd()) {
00575         xml.readNext();
00576 
00577         if (xml.isStartElement() && xml.name() == "p") {
00578             currentParagraph++;
00579         }
00580 
00581         if (currentParagraph == 3) {
00582             if (xml.isCharacters() && !xml.isWhitespace())  {
00583                 QString dataText = xml.text().toString().trimmed();
00584                 if (!skipPlace) {
00585                     skipPlace = true;
00586                 } else {
00587                     if (numParser.indexIn(dataText) != -1 && numParser.capturedTexts().count() >= 3) {
00588                         numberValue = numParser.capturedTexts()[2].toInt();
00589                     }
00590                     switch (dataItem) {
00591                     case Day:
00592                         forecast->period = dataText;
00593                         dataItem++;
00594                         break;
00595                     case Summary:
00596                         forecast->summary = dataText;
00597                         dataItem++;
00598                         break;
00599                     case MaxTemp:
00600                         forecast->tempHigh = numberValue;
00601                         dataItem++;
00602                         break;
00603                     case MinTemp:
00604                         forecast->tempLow = numberValue;
00605                         dataItem++;
00606                         break;
00607                     case WindSpeed:
00608                         forecast->windSpeed = numberValue;
00609                         forecast->windDirection = dataText.split("(")[1].split(")")[0];
00610                         dataItem = 0;
00611                         d->m_weatherData[source].forecasts.append(forecast);
00612                         forecast = new WeatherData::ForecastInfo;
00613                         break;
00614                     };
00615                 }
00616             }
00617         }
00618     }
00619 
00620     delete forecast;
00621 }
00622 
00623 void UKMETIon::setMeasureUnit(const QString& unitType)
00624 {
00625     d->m_measureType = unitType.toInt();
00626 }
00627 
00628 // Not used in this ion yet.
00629 void UKMETIon::setTimezoneFormat(const QString& tz)
00630 {
00631     d->m_timezoneType = tz.toInt(); // Boolean
00632 }
00633 
00634 bool UKMETIon::metricUnit()
00635 {
00636     if (d->m_measureType == KLocale::Metric) {
00637         return true;
00638     }
00639 
00640     // Imperial units
00641     return false;
00642 }
00643 
00644 // Not used in this ion yet.
00645 bool UKMETIon::timezone()
00646 {
00647     if (d->m_timezoneType) {
00648         return true;
00649     }
00650 
00651     // Not UTC, local time
00652     return false;
00653 }
00654 
00655 void UKMETIon::validate(const QString& source)
00656 {
00657     bool beginflag = true;
00658 
00659     if (!d->m_locations.count()) {
00660         QStringList invalidPlace = source.split('|');
00661     if (d->m_place[QString("bbcukmet|%1").arg(invalidPlace[2])].place.isEmpty()) {
00662             setData(source, "validate", QString("bbcukmet|invalid|multiple|%1").arg(invalidPlace[2]));
00663     }
00664     d->m_locations.clear();
00665         return;
00666     } else {
00667         QString placeList;
00668         foreach(const QString &place, d->m_locations) {
00669             if (beginflag) {
00670                 placeList.append(QString("%1|extra|%2").arg(place.split("|")[1]).arg(d->m_place[place].XMLurl));
00671                 beginflag = false;
00672             } else {
00673                 placeList.append(QString("|place|%1|extra|%2").arg(place.split("|")[1]).arg(d->m_place[place].XMLurl));
00674             }
00675         }
00676     if (d->m_locations.count() > 1) {
00677             setData(source, "validate", QString("bbcukmet|valid|multiple|place|%1").arg(placeList));
00678     } else {
00679         placeList[0] = placeList[0].toUpper();
00680         setData(source, "validate", QString("bbcukmet|valid|single|place|%1").arg(placeList));
00681     }
00682     }
00683     d->m_locations.clear();
00684 }
00685 
00686 void UKMETIon::updateWeather(const QString& source)
00687 {
00688     QString weatherSource = source;
00689     weatherSource.replace("bbcukmet|", "bbcukmet|weather|");
00690     weatherSource.append(QString("|%1").arg(d->m_place[source].XMLurl));
00691 
00692     QMap<QString, QString> dataFields;
00693     QStringList fieldList;
00694     QVector<QString> forecastList;
00695     int i = 0;
00696 
00697     setData(weatherSource, "Place", place(source));
00698     setData(weatherSource, "Station", station(source));
00699     setData(weatherSource, "Observation Period", observationTime(source));
00700     setData(weatherSource, "Current Conditions", condition(source));
00701 
00702     setData(weatherSource, "Humidity", humidity(source));
00703     setData(weatherSource, "Visibility", visibility(source));
00704 
00705     dataFields = temperature(source);
00706     setData(weatherSource, "Temperature", dataFields["temperature"]);
00707     setData(weatherSource, "Temperature Unit", dataFields["temperatureUnit"]);
00708 
00709     dataFields = pressure(source);
00710     setData(weatherSource, "Pressure", dataFields["pressure"]);
00711     setData(weatherSource, "Pressure Unit", dataFields["pressureUnit"]);
00712     setData(weatherSource, "Pressure Tendency", dataFields["pressureTendency"]);
00713 
00714     dataFields = wind(source);
00715     setData(weatherSource, "Wind Speed", dataFields["windSpeed"]);
00716     setData(weatherSource, "Wind Speed Unit", dataFields["windUnit"]);
00717     setData(weatherSource, "Wind Direction", dataFields["windDirection"]);
00718 
00719     // 5 Day forecast info
00720     forecastList = forecasts(source);
00721 
00722     QString windSpeed;
00723     QString windUnit;
00724     foreach(const QString &forecastItem, forecastList) {
00725         fieldList = forecastItem.split('|');
00726         if (metricUnit()) {
00727                 windSpeed = QString::number(WeatherFormula::milesToKM(fieldList[4].toFloat()), 'f', 1);
00728                 windUnit = "km/h";
00729         } else {
00730                 windSpeed = fieldList[4];
00731                 windUnit = "mph";
00732         }
00733 
00734         setData(weatherSource, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7") \
00735                 .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[2]).arg(fieldList[3]) \
00736                 .arg(windSpeed).arg(windUnit).arg(fieldList[5]));
00737         i++;
00738     }
00739 
00740     setData(weatherSource, "Credit", "Supported by backstage.bbc.co.uk / Data from UK MET Office");
00741 }
00742 
00743 QString UKMETIon::place(const QString& source)
00744 {
00745     return d->m_weatherData[source].stationName;
00746 }
00747 
00748 QString UKMETIon::station(const QString& source)
00749 {
00750     return d->m_weatherData[source].stationName;
00751 }
00752 
00753 QString UKMETIon::observationTime(const QString& source)
00754 {
00755     return d->m_weatherData[source].obsTime;
00756 }
00757 
00758 QString UKMETIon::condition(const QString& source)
00759 {
00760     return d->m_weatherData[source].condition;
00761 }
00762 
00763 QMap<QString, QString> UKMETIon::temperature(const QString& source)
00764 {
00765     QMap<QString, QString> temperatureInfo;
00766 
00767     if (metricUnit()) {
00768         temperatureInfo.insert("temperature", QString("%1").arg(d->m_weatherData[source].temperature_C));
00769         temperatureInfo.insert("temperatureUnit", QString("%1C").arg(QChar(176)));
00770     } else {
00771         temperatureInfo.insert("temperature", QString("%1").arg(d->m_weatherData[source].temperature_F));
00772         temperatureInfo.insert("temperatureUnit", QString("%1F").arg(QChar(176)));
00773     }
00774     return temperatureInfo;
00775 }
00776 
00777 QMap<QString, QString> UKMETIon::wind(const QString& source)
00778 {
00779     QMap<QString, QString> windInfo;
00780     if (d->m_weatherData[source].windSpeed_miles == "N/A") {
00781         windInfo.insert("windSpeed", "N/A");
00782         windInfo.insert("windUnit", "N/A");
00783     } else {
00784         if (metricUnit()) {
00785                 windInfo.insert("windSpeed", QString::number(WeatherFormula::milesToKM(d->m_weatherData[source].windSpeed_miles.toFloat()), 'f', 1));
00786                 windInfo.insert("windUnit", "km/h");
00787         } else {
00788                 windInfo.insert("windSpeed", QString(d->m_weatherData[source].windSpeed_miles));
00789                 windInfo.insert("windUnit", "mph");
00790         }
00791     }
00792     windInfo.insert("windDirection", d->m_weatherData[source].windDirection);
00793     return windInfo;
00794 }
00795 
00796 QString UKMETIon::humidity(const QString& source)
00797 {
00798     if (d->m_weatherData[source].humidity == "N/A%") {
00799         return "N/A";
00800     }
00801     return d->m_weatherData[source].humidity;
00802 }
00803 
00804 QString UKMETIon::visibility(const QString& source)
00805 {
00806     return d->m_weatherData[source].visibilityStr;
00807 }
00808 
00809 QMap<QString, QString> UKMETIon::pressure(const QString& source)
00810 {
00811     QMap<QString, QString> pressureInfo;
00812     if (d->m_weatherData[source].pressure == "N/A") {
00813         pressureInfo.insert("pressure", "N/A");
00814         return pressureInfo;
00815     }
00816 
00817     if (metricUnit()) {
00818         pressureInfo.insert("pressure", QString::number(WeatherFormula::millibarsToKilopascals(d->m_weatherData[source].pressure.toFloat()), 'f', 1));
00819         pressureInfo.insert("pressureUnit", "kPa");
00820     } else {
00821         pressureInfo.insert("pressure", QString::number(WeatherFormula::millibarsToInches(d->m_weatherData[source].pressure.toFloat()), 'f', 2));
00822         pressureInfo.insert("pressureUnit", "in");
00823     }
00824 
00825     pressureInfo.insert("pressureTendency", d->m_weatherData[source].pressureTendency);
00826     return pressureInfo;
00827 }
00828 
00829 QVector<QString> UKMETIon::forecasts(const QString& source)
00830 {
00831     QVector<QString> forecastData;
00832 
00833     for (int i = 0; i < d->m_weatherData[source].forecasts.size(); ++i) {
00834         forecastData.append(QString("%1|%2|%3|%4|%5|%6") \
00835                             .arg(d->m_weatherData[source].forecasts[i]->period) \
00836                             .arg(d->m_weatherData[source].forecasts[i]->summary) \
00837                             .arg(d->m_weatherData[source].forecasts[i]->tempHigh) \
00838                             .arg(d->m_weatherData[source].forecasts[i]->tempLow) \
00839                             .arg(d->m_weatherData[source].forecasts[i]->windSpeed) \
00840                             .arg(d->m_weatherData[source].forecasts[i]->windDirection));
00841     }
00842 
00843     return forecastData;
00844 }
00845 
00846 #include "ion_bbcukmet.moc"

Engines

Skip menu "Engines"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal