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

Engines

ion_noaa.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007-2008 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 NOAA's National Weather Service XML data */
00021 
00022 #include "ion_noaa.h"
00023 
00024 class NOAAIon::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 stateName;
00037         QString stationName;
00038         QString XMLurl;
00039         QString sourceOptions;
00040     };
00041 
00042 public:
00043     // Key dicts
00044     QHash<QString, NOAAIon::Private::XMLMapInfo> m_place;
00045     QHash<QString, QString> m_locations;
00046     QString m_state;
00047     QString m_station_name;
00048     QString m_xmlurl;
00049 
00050     // Weather information
00051     QHash<QString, WeatherData> m_weatherData;
00052 
00053     // Store KIO jobs
00054     QMap<KJob *, QXmlStreamReader*> m_jobXml;
00055     QMap<KJob *, QString> m_jobList;
00056     QXmlStreamReader m_xmlSetup;
00057     KUrl *m_url;
00058     KIO::TransferJob *m_job;
00059 
00060     QDateTime m_dateFormat;
00061 };
00062 
00063 QMap<QString, IonInterface::WindDirections> NOAAIon::setupWindIconMappings(void)
00064 {
00065     QMap<QString, WindDirections> windDir;
00066     windDir["north"] = N;
00067     windDir["northeast"] = NE;
00068     windDir["south"] = S;
00069     windDir["southwest"] = SW;
00070     windDir["east"] = E;
00071     windDir["southeast"] = SE;
00072     windDir["west"] = W;
00073     windDir["northwest"] = NW;
00074     windDir["calm"] = VR;
00075     return windDir;
00076 }
00077 
00078 QMap<QString, IonInterface::ConditionIcons> NOAAIon::setupConditionIconMappings(void)
00079 {
00080 
00081     QMap<QString, ConditionIcons> conditionList;
00082     return conditionList;
00083 }
00084 
00085 QMap<QString, IonInterface::ConditionIcons> const& NOAAIon::conditionIcons(void)
00086 {
00087     static QMap<QString, ConditionIcons> const condval = setupConditionIconMappings();
00088     return condval;
00089 }
00090 
00091 QMap<QString, IonInterface::WindDirections> const& NOAAIon::windIcons(void)
00092 {
00093     static QMap<QString, WindDirections> const wval = setupWindIconMappings();
00094     return wval;
00095 }
00096 
00097 // ctor, dtor
00098 NOAAIon::NOAAIon(QObject *parent, const QVariantList &args)
00099         : IonInterface(parent, args), d(new Private())
00100 {
00101     Q_UNUSED(args)
00102 }
00103 
00104 NOAAIon::~NOAAIon()
00105 {
00106     // Destroy dptr
00107     delete d;
00108 }
00109 
00110 // Get the master list of locations to be parsed
00111 void NOAAIon::init()
00112 {
00113     // Get the real city XML URL so we can parse this
00114     getXMLSetup();
00115 }
00116 
00117 QStringList NOAAIon::validate(const QString& source) const
00118 {
00119     QStringList placeList;
00120     QHash<QString, QString>::const_iterator it = d->m_locations.constBegin();
00121     while (it != d->m_locations.constEnd()) {
00122         if (it.value().toLower().contains(source.toLower())) {
00123             placeList.append(QString("place|%1").arg(it.value().split('|')[1]));
00124         }
00125         ++it;
00126     }
00127 
00128     // Check if placeList is empty if so, return nothing.
00129     if (placeList.isEmpty()) {
00130         return QStringList();
00131     }
00132 
00133     placeList.sort();
00134     return placeList;
00135 }
00136 
00137 bool NOAAIon::updateIonSource(const QString& source)
00138 {
00139     // We expect the applet to send the source in the following tokenization:
00140     // ionname:validate:place_name - Triggers validation of place
00141     // ionname:weather:place_name - Triggers receiving weather of place
00142 
00143     QStringList sourceAction = source.split('|');
00144 
00145     // Guard: if the size of array is not 2 then we have bad data, return an error
00146     if (sourceAction.size() < 2) {
00147         setData(source, "validate", QString("noaa|timeout"));
00148         return true;
00149     }
00150     
00151     if (sourceAction[1] == QString("validate")) {
00152         kDebug() << "Initiate Validating of place: " << sourceAction[2];
00153         QStringList result = validate(QString("%1|%2").arg(sourceAction[0]).arg(sourceAction[2]));
00154 
00155         if (result.size() == 1) {
00156             setData(source, "validate", QString("noaa|valid|single|%1").arg(result.join("|")));
00157             return true;
00158         } else if (result.size() > 1) {
00159             setData(source, "validate", QString("noaa|valid|multiple|%1").arg(result.join("|")));
00160             return true;
00161         } else if (result.size() == 0) {
00162             setData(source, "validate", QString("noaa|invalid|single|%1").arg(sourceAction[2]));
00163             return true;
00164         }
00165 
00166     } else if (sourceAction[1] == QString("weather")) {
00167         getXMLData(source);
00168         return true;
00169     }
00170     return false;
00171 }
00172 
00173 // Parses city list and gets the correct city based on ID number
00174 void NOAAIon::getXMLSetup()
00175 {
00176     d->m_url = new KUrl("http://www.weather.gov/data/current_obs/index.xml");
00177 
00178     KIO::TransferJob *job = KIO::get(d->m_url->url(), KIO::NoReload, KIO::HideProgressInfo);
00179 
00180     if (job) {
00181         connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00182                 SLOT(setup_slotDataArrived(KIO::Job *, const QByteArray &)));
00183         connect(job, SIGNAL(result(KJob *)), this, SLOT(setup_slotJobFinished(KJob *)));
00184     }
00185 }
00186 
00187 // Gets specific city XML data
00188 void NOAAIon::getXMLData(const QString& source)
00189 {
00190     KUrl url;
00191 
00192     QString dataKey = source;
00193     dataKey.remove("|weather");
00194     url = d->m_place[dataKey].XMLurl;
00195 
00196     kDebug() << "URL Location: " << url.url();
00197 
00198     // If this is empty we have no valid data, send out an error and abort.
00199     //
00200     if (url.url().isEmpty()) { 
00201         setData(source, "validate", QString("noaa|timeout"));
00202         return;
00203     }
00204 
00205     d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
00206     d->m_jobXml.insert(d->m_job, new QXmlStreamReader);
00207     d->m_jobList.insert(d->m_job, source);
00208 
00209     if (d->m_job) {
00210         connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
00211                 SLOT(slotDataArrived(KIO::Job *, const QByteArray &)));
00212         connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(slotJobFinished(KJob *)));
00213     }
00214 }
00215 
00216 void NOAAIon::setup_slotDataArrived(KIO::Job *job, const QByteArray &data)
00217 {
00218     Q_UNUSED(job)
00219 
00220     if (data.isEmpty()) {
00221         return;
00222     }
00223 
00224     // Send to xml.
00225     d->m_xmlSetup.addData(data);
00226 }
00227 
00228 void NOAAIon::slotDataArrived(KIO::Job *job, const QByteArray &data)
00229 {
00230     if (data.isEmpty() || !d->m_jobXml.contains(job)) {
00231         return;
00232     }
00233 
00234     // Send to xml.
00235     d->m_jobXml[job]->addData(data);
00236 }
00237 
00238 void NOAAIon::slotJobFinished(KJob *job)
00239 {
00240     // Dual use method, if we're fetching location data to parse we need to do this first
00241     setData(d->m_jobList[job], Data());
00242     readXMLData(d->m_jobList[job], *d->m_jobXml[job]);
00243     d->m_jobList.remove(job);
00244     delete d->m_jobXml[job];
00245     d->m_jobXml.remove(job);
00246 }
00247 
00248 void NOAAIon::setup_slotJobFinished(KJob *job)
00249 {
00250     Q_UNUSED(job)
00251     readXMLSetup();
00252     setInitialized(true);
00253 }
00254 
00255 void NOAAIon::parseStationID()
00256 {
00257     QString tmp;
00258     while (!d->m_xmlSetup.atEnd()) {
00259         d->m_xmlSetup.readNext();
00260 
00261         if (d->m_xmlSetup.isEndElement() && d->m_xmlSetup.name() == "station") {
00262             break;
00263         }
00264 
00265         if (d->m_xmlSetup.isStartElement()) {
00266             if (d->m_xmlSetup.name() == "state") {
00267                 d->m_state = d->m_xmlSetup.readElementText();
00268             } else if (d->m_xmlSetup.name() == "station_name") {
00269                 d->m_station_name = d->m_xmlSetup.readElementText();
00270             } else if (d->m_xmlSetup.name() == "xml_url") {
00271                 d->m_xmlurl = d->m_xmlSetup.readElementText();
00272 
00273                 tmp = "noaa|" + d->m_station_name + ", " + d->m_state; // Build the key name.
00274                 d->m_place[tmp].stateName = d->m_state;
00275                 d->m_place[tmp].stationName = d->m_station_name;
00276                 d->m_place[tmp].XMLurl = d->m_xmlurl.replace("http://", "http://www.");
00277 
00278                 d->m_locations[tmp] = tmp;
00279             } else {
00280                 parseUnknownElement(d->m_xmlSetup);
00281             }
00282         }
00283     }
00284 }
00285 
00286 void NOAAIon::parseStationList()
00287 {
00288     while (!d->m_xmlSetup.atEnd()) {
00289         d->m_xmlSetup.readNext();
00290 
00291         if (d->m_xmlSetup.isEndElement()) {
00292             break;
00293         }
00294 
00295         if (d->m_xmlSetup.isStartElement()) {
00296             if (d->m_xmlSetup.name() == "station") {
00297                 parseStationID();
00298             } else {
00299                 parseUnknownElement(d->m_xmlSetup);
00300             }
00301         }
00302     }
00303 }
00304 
00305 // Parse the city list and store into a QMap
00306 bool NOAAIon::readXMLSetup()
00307 {
00308     while (!d->m_xmlSetup.atEnd()) {
00309         d->m_xmlSetup.readNext();
00310 
00311         if (d->m_xmlSetup.isStartElement()) {
00312             if (d->m_xmlSetup.name() == "wx_station_index") {
00313                 parseStationList();
00314             }
00315         }
00316     }
00317     return !d->m_xmlSetup.error();
00318 }
00319 
00320 WeatherData NOAAIon::parseWeatherSite(WeatherData& data, QXmlStreamReader& xml)
00321 {
00322     data.temperature_C = "N/A";
00323     data.temperature_F = "N/A";
00324     data.dewpoint_C = "N/A";
00325     data.dewpoint_F = "N/A";
00326     data.weather = "N/A";
00327     data.stationID = "N/A";
00328     data.pressure = "N/A";
00329     data.visibility = "N/A";
00330     data.humidity = "N/A";
00331     data.windSpeed = "N/A";
00332     data.windGust = "N/A";
00333     data.windchill_F = "N/A";
00334     data.windchill_C = "N/A";
00335     data.heatindex_F = "N/A";
00336     data.heatindex_C = "N/A";
00337 
00338     while (!xml.atEnd()) {
00339         xml.readNext();
00340 
00341         if (xml.isStartElement()) {
00342             if (xml.name() == "location") {
00343                 data.locationName = xml.readElementText();
00344             } else if (xml.name() == "station_id") {
00345                 data.stationID = xml.readElementText();
00346             } else if (xml.name() == "observation_time") {
00347                 data.observationTime = xml.readElementText();
00348                 QStringList tmpDateStr = data.observationTime.split(' ');
00349                 data.observationTime = QString("%1 %2").arg(tmpDateStr[5]).arg(tmpDateStr[6]);
00350                 d->m_dateFormat = QDateTime::fromString(data.observationTime, "h:mm ap");
00351                 data.iconPeriodHour = d->m_dateFormat.toString("HH");
00352                 data.iconPeriodAP = d->m_dateFormat.toString("ap");
00353 
00354             } else if (xml.name() == "weather") {
00355                 data.weather = xml.readElementText();
00356                 // Pick which icon set depending on period of day
00357             } else if (xml.name() == "temp_f") {
00358                 data.temperature_F = xml.readElementText();
00359             } else if (xml.name() == "temp_c") {
00360                 data.temperature_C = xml.readElementText();
00361             } else if (xml.name() == "relative_humidity") {
00362                 data.humidity = xml.readElementText();
00363             } else if (xml.name() == "wind_dir") {
00364                 data.windDirection = xml.readElementText();
00365             } else if (xml.name() == "wind_mph") {
00366                 data.windSpeed = xml.readElementText();
00367             } else if (xml.name() == "wind_gust_mph") {
00368                 data.windGust = xml.readElementText();
00369             } else if (xml.name() == "pressure_in") {
00370                 data.pressure = xml.readElementText();
00371             } else if (xml.name() == "dewpoint_f") {
00372                 data.dewpoint_F = xml.readElementText();
00373             } else if (xml.name() == "dewpoint_c") {
00374                 data.dewpoint_C = xml.readElementText();
00375             } else if (xml.name() == "heat_index_f") {
00376                 data.heatindex_F = xml.readElementText();
00377             } else if (xml.name() == "heat_index_c") {
00378                 data.heatindex_C = xml.readElementText();
00379             } else if (xml.name() == "windchill_f") {
00380                 data.windchill_F = xml.readElementText();
00381             } else if (xml.name() == "windchill_c") {
00382                 data.windchill_C = xml.readElementText();
00383             } else if (xml.name() == "visibility_mi") {
00384                 data.visibility = xml.readElementText();
00385             } else {
00386                 parseUnknownElement(xml);
00387             }
00388         }
00389     }
00390     return data;
00391 }
00392 
00393 // Parse Weather data main loop, from here we have to decend into each tag pair
00394 bool NOAAIon::readXMLData(const QString& source, QXmlStreamReader& xml)
00395 {
00396     WeatherData data;
00397 
00398     while (!xml.atEnd()) {
00399         xml.readNext();
00400 
00401         if (xml.isEndElement()) {
00402             break;
00403         }
00404 
00405         if (xml.isStartElement()) {
00406             if (xml.name() == "current_observation") {
00407                 data = parseWeatherSite(data, xml);
00408             } else {
00409                 parseUnknownElement(xml);
00410             }
00411         }
00412     }
00413 
00414     d->m_weatherData[source] = data;
00415     updateWeather(source);
00416     return !xml.error();
00417 }
00418 
00419 // handle when no XML tag is found
00420 void NOAAIon::parseUnknownElement(QXmlStreamReader& xml)
00421 {
00422 
00423     while (!xml.atEnd()) {
00424         xml.readNext();
00425 
00426         if (xml.isEndElement()) {
00427             break;
00428         }
00429 
00430         if (xml.isStartElement()) {
00431             parseUnknownElement(xml);
00432         }
00433     }
00434 }
00435 
00436 void NOAAIon::updateWeather(const QString& source)
00437 {
00438     QMap<QString, QString> dataFields;
00439     QStringList fieldList;
00440 
00441     setData(source, "Country", country(source));
00442     setData(source, "Place", place(source));
00443     setData(source, "Station", station(source));
00444 
00445     // Real weather - Current conditions
00446     setData(source, "Observation Period", observationTime(source));
00447     setData(source, "Current Conditions", condition(source));
00448 
00449 // FIXME: We'll need major fuzzy logic, this isn't pretty: http://www.weather.gov/xml/current_obs/weather.php
00450     //QMap<QString, ConditionIcons> conditionList;
00451     //conditionList = conditionIcons();
00452 
00453 /*
00454     if ((periodHour(source) >= 0 && periodHour(source) < 6) || (periodHour(source) >= 18)) {
00455         // Night
00456         // - Fill in condition fuzzy logic 
00457     } else {
00458         // Day
00459         // - Fill in condition fuzzy logic
00460     }
00461 */
00462     setData(source, "Condition Icon", "weather-none-available");
00463 
00464     dataFields = temperature(source);
00465     setData(source, "Temperature", dataFields["temperature"]);
00466 
00467     if (dataFields["temperature"] != "N/A") {
00468         setData(source, "Temperature Unit", dataFields["temperatureUnit"]);
00469     }
00470 
00471     // Do we have a comfort temperature? if so display it
00472     if (dataFields["comfortTemperature"] != "N/A") {
00473         if (d->m_weatherData[source].windchill_F != "NA") {
00474             setData(source, "Windchill", QString("%1").arg(dataFields["comfortTemperature"]));
00475             setData(source, "Humidex", "N/A");
00476         }
00477         if (d->m_weatherData[source].heatindex_F != "NA" && d->m_weatherData[source].temperature_F.toInt() != d->m_weatherData[source].heatindex_F.toInt()) {
00478             setData(source, "Humidex", QString("%1").arg(dataFields["comfortTemperature"]));
00479             setData(source, "Windchill", "N/A");
00480         }
00481     } else {
00482         setData(source, "Windchill", "N/A");
00483         setData(source, "Humidex", "N/A");
00484     }
00485 
00486     setData(source, "Dewpoint", dewpoint(source));
00487     if (dewpoint(source) != "N/A") {
00488         setData(source, "Dewpoint Unit", dataFields["temperatureUnit"]);
00489     }
00490 
00491     dataFields = pressure(source);
00492     setData(source, "Pressure", dataFields["pressure"]);
00493 
00494     if (dataFields["pressure"] != "N/A") {
00495         setData(source, "Pressure Unit", dataFields["pressureUnit"]);
00496     }
00497 
00498     dataFields = visibility(source);
00499     setData(source, "Visibility", dataFields["visibility"]);
00500 
00501     if (dataFields["visibility"] != "N/A") {
00502         setData(source, "Visibility Unit", dataFields["visibilityUnit"]);
00503     }
00504 
00505     setData(source, "Humidity", humidity(source));
00506 
00507     // Set number of forecasts per day/night supported, none for this ion right now
00508     setData(source, QString("Total Weather Days"), 0);
00509 
00510     dataFields = wind(source);
00511     setData(source, "Wind Speed", dataFields["windSpeed"]);
00512 
00513     if (dataFields["windSpeed"] != "Calm") {
00514         setData(source, "Wind Speed Unit", dataFields["windUnit"]);
00515     }
00516 
00517     setData(source, "Wind Gust", dataFields["windGust"]);
00518     setData(source, "Wind Gust Unit", dataFields["windGustUnit"]);
00519     setData(source, "Wind Direction", getWindDirectionIcon(windIcons(), dataFields["windDirection"].toLower()));
00520     setData(source, "Credit", "Data provided by NOAA National Weather Service");
00521 }
00522 
00523 QString NOAAIon::country(const QString& source)
00524 {
00525     Q_UNUSED(source);
00526     return QString("USA");
00527 }
00528 QString NOAAIon::place(const QString& source)
00529 {
00530     return d->m_weatherData[source].locationName;
00531 }
00532 QString NOAAIon::station(const QString& source)
00533 {
00534     return d->m_weatherData[source].stationID;
00535 }
00536 
00537 QString NOAAIon::observationTime(const QString& source)
00538 {
00539     return d->m_weatherData[source].observationTime;
00540 }
00541 
00542 /*
00543 bool NOAAIon::night(const QString& source)
00544 {
00545     if (d->m_weatherData[source].iconPeriodAP == "pm") {
00546         return true;
00547     }
00548     return false;
00549 }
00550 */
00551 
00552 int NOAAIon::periodHour(const QString& source)
00553 {
00554     return d->m_weatherData[source].iconPeriodHour.toInt();
00555 }
00556 
00557 QString NOAAIon::condition(const QString& source)
00558 {
00559     if (d->m_weatherData[source].weather.isEmpty() || d->m_weatherData[source].weather == "NA") {
00560         d->m_weatherData[source].weather = "N/A";
00561     }
00562     return d->m_weatherData[source].weather;
00563 }
00564 
00565 QString NOAAIon::dewpoint(const QString& source)
00566 {
00567     return d->m_weatherData[source].dewpoint_F;
00568 }
00569 
00570 QString NOAAIon::humidity(const QString& source)
00571 {
00572     if (d->m_weatherData[source].humidity == "NA") {
00573         return QString("N/A");
00574     } else {
00575         return QString("%1%").arg(d->m_weatherData[source].humidity);
00576     }
00577 }
00578 
00579 QMap<QString, QString> NOAAIon::visibility(const QString& source)
00580 {
00581     QMap<QString, QString> visibilityInfo;
00582     if (d->m_weatherData[source].visibility.isEmpty()) {
00583         visibilityInfo.insert("visibility", QString("N/A"));
00584         return visibilityInfo;
00585     }
00586     visibilityInfo.insert("visibility", d->m_weatherData[source].visibility);
00587     visibilityInfo.insert("visibilityUnit", QString::number(WeatherUtils::Miles));
00588     return visibilityInfo;
00589 }
00590 
00591 QMap<QString, QString> NOAAIon::temperature(const QString& source)
00592 {
00593     QMap<QString, QString> temperatureInfo;
00594     temperatureInfo.insert("temperature", d->m_weatherData[source].temperature_F);
00595     temperatureInfo.insert("temperatureUnit", QString::number(WeatherUtils::Fahrenheit));
00596     temperatureInfo.insert("comfortTemperature", "N/A");
00597 
00598     if (d->m_weatherData[source].heatindex_F != "NA" && d->m_weatherData[source].windchill_F == "NA") {
00599         temperatureInfo.insert("comfortTemperature", d->m_weatherData[source].heatindex_F);
00600     }
00601 
00602     if (d->m_weatherData[source].windchill_F != "NA" && d->m_weatherData[source].heatindex_F == "NA") {
00603         temperatureInfo.insert("comfortTemperature", d->m_weatherData[source].windchill_F);
00604     }
00605 
00606     return temperatureInfo;
00607 }
00608 
00609 QMap<QString, QString> NOAAIon::pressure(const QString& source)
00610 {
00611     QMap<QString, QString> pressureInfo;
00612     if (d->m_weatherData[source].pressure.isEmpty()) {
00613         pressureInfo.insert("pressure", "N/A");
00614         return pressureInfo;
00615     }
00616 
00617     pressureInfo.insert("pressure", d->m_weatherData[source].pressure);
00618     pressureInfo.insert("pressureUnit", QString::number(WeatherUtils::InchesHG));
00619     return pressureInfo;
00620 }
00621 
00622 QMap<QString, QString> NOAAIon::wind(const QString& source)
00623 {
00624     QMap<QString, QString> windInfo;
00625 
00626     // May not have any winds
00627     if (d->m_weatherData[source].windSpeed == "NA") {
00628         windInfo.insert("windSpeed", "Calm");
00629         windInfo.insert("windUnit", QString::number(WeatherUtils::NoUnit));
00630     } else {
00631         windInfo.insert("windSpeed", QString::number(d->m_weatherData[source].windSpeed.toFloat(), 'f', 1));
00632         windInfo.insert("windUnit", QString::number(WeatherUtils::MilesAnHour));
00633     }
00634 
00635     // May not always have gusty winds
00636     if (d->m_weatherData[source].windGust == "NA") {
00637         windInfo.insert("windGust", "N/A");
00638         windInfo.insert("windGustUnit", QString::number(WeatherUtils::NoUnit));
00639     } else {
00640         windInfo.insert("windGust", QString::number(d->m_weatherData[source].windGust.toFloat(), 'f', 1));
00641         windInfo.insert("windGustUnit", QString::number(WeatherUtils::MilesAnHour));
00642     }
00643 
00644     if (d->m_weatherData[source].windDirection.isEmpty()) {
00645         windInfo.insert("windDirection", "N/A");
00646     } else {
00647         windInfo.insert("windDirection", d->m_weatherData[source].windDirection);
00648     }
00649     return windInfo;
00650 }
00651 
00652 #include "ion_noaa.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
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
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