rendered paste bodyIndex: weatherengine.cpp===================================================================--- weatherengine.cpp (revision 724674)+++ weatherengine.cpp (working copy)@@ -21,7 +21,6 @@ #include <KServiceTypeTrader> #include <KDateTime> #include <KLocale>-#include <QTimer> #include "ions/ion.h" class WeatherEngine::Private@@ -29,10 +28,26 @@ public: Private() {} ~Private() {- m_ions.clear();+ qDeleteAll(m_ions); } - QTimer *m_timer;+ IonInterface* ionForSource(const QString& name)+ {+ int offset = name.indexOf(':');++ if (offset < 1) {+ return 0;+ }++ QString ionName = name.left(offset);++ if (!this->m_ions.contains(ionName)) {+ return 0;+ }++ return this->m_ions[ionName];+ }+ IonInterface::IonDict m_ions; KDateTime m_localTime; };@@ -51,7 +66,6 @@ // Loads an Ion plugin given a plugin name found via KService. IonInterface* WeatherEngine::loadIon(const KService::Ptr& service) {- IonInterface *ion = 0; QString plugName = service->property("X-IonName").toString(); IonInterface::IonDict::const_iterator it = d->m_ions.find(plugName);@@ -135,7 +149,6 @@ return; } ion->connectSource(source, this);- ion->fetch(); } void WeatherEngine::removeIonSource(const QString& source)@@ -167,11 +180,6 @@ foreach(KService::Ptr service, knownIons()) { loadIon(service); }-- // Setup a master time to ping each Ion for new data.- d->m_timer = new QTimer(this);- d->m_timer->setSingleShot(false);- connect(d->m_timer, SIGNAL(timeout()), this, SLOT(updateData())); } // dtor@@ -182,31 +190,42 @@ } // Setup each Ion for the first time-bool WeatherEngine::sourceRequested(const QString &name)+bool WeatherEngine::sourceRequested(const QString &source) {- // Pass values to set when getting data from the ion.- foreach(IonInterface *ion, d->m_ions) {- // Before we use the timer, get the data.- ion->setSource(name);- kDebug() << "sourceRequested()";+ IonInterface *ion = d->ionForSource(source);++ if (!ion) {+ kDebug() << "BAD ION!!!!!!!!!!";+ return false; } - /* FIXME: Make the timer value configurable in 30 minute intervals via Applet */- if (!d->m_timer->isActive())- d->m_timer->start(50000);+ // Pass values to set when getting data from the ion. - updateData();+ QStringList tokens = source.split(':'); + if (tokens.size() < 1) {+ kDebug() << "Invalid string :-(";+ return false;+ }++ kDebug() << "Source requested: " << tokens[1];+ ion->connectSource(tokens[1], this);+ kDebug() << "sourceRequested()"; return true; } // SLOT: update the Applet with new data from all ions loaded.-void WeatherEngine::updateData()+bool WeatherEngine::updateSource(const QString& source) {- foreach(IonInterface *ion, d->m_ions) {- ion->fetch();- ion->updateData();+ IonInterface *ion = d->ionForSource(source);+ + kDebug() << "*********** TIMEOUT ********** Get new push of data!";+ if (!ion) {+ return false; }++ ion->updateSource(source);+ return true; } #include "weatherengine.moc"Index: ions/ion_envcan.cpp===================================================================--- ions/ion_envcan.cpp (revision 724674)+++ ions/ion_envcan.cpp (working copy)@@ -104,10 +104,11 @@ } // Get a specific Ion's data-void EnvCanadaIon::fetch()+bool EnvCanadaIon::updateIonSource(const QString& source) {- // Go read the city's XML file- getXMLData();+ kDebug() << "Getting WEATHER FOR ==========> " << source;+ getXMLData(source);+ return true; } // Parses city list and gets the correct city based on ID number@@ -126,27 +127,21 @@ } // Gets specific city XML data-void EnvCanadaIon::getXMLData()+void EnvCanadaIon::getXMLData(const QString& source) { KUrl url;- foreach(QString key, this->ionSourceDict()) {- if (!validLocation(key)) {- continue;- } else {- url = "http://dd.weatheroffice.ec.gc.ca/EC_sites/xml/" + d->m_place[key].territoryName + "/" + d->m_place[key].cityCode + "_e.xml";- }+ url = "http://dd.weatheroffice.ec.gc.ca/EC_sites/xml/" + d->m_place[source].territoryName + "/" + d->m_place[source].cityCode + "_e.xml"; - //kDebug() << "URL Location: " << url.url();+ kDebug() << "URL Location: " << url.url(); - d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);- d->m_jobXml.insert(d->m_job, new QXmlStreamReader);- d->m_jobList.insert(d->m_job, key);+ d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);+ d->m_jobXml.insert(d->m_job, new QXmlStreamReader);+ d->m_jobList.insert(d->m_job, source); - if (d->m_job) {- connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,- SLOT(slotDataArrived(KIO::Job *, const QByteArray &)));- connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(slotJobFinished(KJob *)));- }+ if (d->m_job) {+ connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,+ SLOT(slotDataArrived(KIO::Job *, const QByteArray &)));+ connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(slotJobFinished(KJob *))); } } @@ -186,9 +181,7 @@ { Q_UNUSED(job) readXMLSetup();-- // Do the XML fetching for the correct city.- getXMLData();+ this->setInitialized(true); } // Parse the city list and store into a QMap@@ -261,11 +254,11 @@ } // Parse Weather data main loop, from here we have to decend into each tag pair-bool EnvCanadaIon::readXMLData(QString key, QXmlStreamReader& xml)+bool EnvCanadaIon::readXMLData(const QString& source, QXmlStreamReader& xml) { WeatherData data; data.comforttemp = "N/A";- data.shortTerritoryName = d->m_place[key].territoryName;+ data.shortTerritoryName = d->m_place[source].territoryName; while (!xml.atEnd()) { xml.readNext(); @@ -282,8 +275,8 @@ } } - d->m_weatherData[key] = data;- updateData();+ d->m_weatherData[source] = data;+ updateWeather(source); return !xml.error(); } @@ -853,135 +846,124 @@ } } -void EnvCanadaIon::updateData()+void EnvCanadaIon::updateWeather(const QString& source) {- QVector<QString> sources; QMap<QString, QString> dataFields; QStringList fieldList; QVector<QString> forecastList; int i = 0; - sources = this->ionSourceDict();- foreach(QString keyname, sources) {- // Does this place exist?- if (!this->validLocation(keyname)) {- kDebug() << "EnvCanadaIon::updateData() " << keyname << " is not a valid location";- //setData(keyname, "Invalid Place", "Invalid location");- continue;- }- setData(keyname, "Country", this->country(keyname));- setData(keyname, "Place", QString("%1, %2").arg(this->city(keyname)).arg(this->territory(keyname)));- setData(keyname, "Region", this->region(keyname));- setData(keyname, "Airport Code", this->station(keyname));+ setData(source, "Country", this->country(source));+ setData(source, "Place", QString("%1, %2").arg(this->city(source)).arg(this->territory(source)));+ setData(source, "Region", this->region(source));+ setData(source, "Airport Code", this->station(source)); - // Real weather - Current conditions- setData(keyname, "Observations At", this->observationTime(keyname));- setData(keyname, "Current Conditions", this->condition(keyname));- dataFields = this->temperature(keyname);- setData(keyname, "Temperature", dataFields["temperature"]);+ // Real weather - Current conditions+ setData(source, "Observations At", this->observationTime(source));+ setData(source, "Current Conditions", this->condition(source));+ dataFields = this->temperature(source);+ setData(source, "Temperature", dataFields["temperature"]); - // Do we have a comfort temperature? if so display it- if (dataFields["comfortTemperature"] != "N/A" && !dataFields["comfortTemperature"].isEmpty()) {- if (dataFields["comfortTemperature"].toFloat() <= 0 || (dataFields["comfortTemperature"].toFloat() <= 32 && !d->m_useMetric)) {- setData(keyname, "Windchill", QString("%1%2").arg(dataFields["comfortTemperature"]).arg(QChar(176)));- } else {- setData(keyname, "Humidex", QString("%1%2").arg(dataFields["comfortTemperature"]).arg(QChar(176)));- }+ // Do we have a comfort temperature? if so display it+ if (dataFields["comfortTemperature"] != "N/A" && !dataFields["comfortTemperature"].isEmpty()) {+ if (dataFields["comfortTemperature"].toFloat() <= 0 || (dataFields["comfortTemperature"].toFloat() <= 32 && !d->m_useMetric)) {+ setData(source, "Windchill", QString("%1%2").arg(dataFields["comfortTemperature"]).arg(QChar(176)));+ } else {+ setData(source, "Humidex", QString("%1%2").arg(dataFields["comfortTemperature"]).arg(QChar(176))); }+ } - setData(keyname, "Dewpoint", this->dewpoint(keyname));- dataFields = this->pressure(keyname);- setData(keyname, "Pressure", dataFields["pressure"]);- setData(keyname, "Pressure Tendency", dataFields["pressureTendency"]);- setData(keyname, "Visibility", this->visibility(keyname));- setData(keyname, "Humidity", this->humidity(keyname));- dataFields = this->wind(keyname);- setData(keyname, "Wind Speed", dataFields["windSpeed"]);- setData(keyname, "Wind Speed Unit", dataFields["windUnit"]);- setData(keyname, "Wind Gust", dataFields["windGust"]);- setData(keyname, "Wind Gust Unit", dataFields["windGustUnit"]);- setData(keyname, "Wind Direction", dataFields["windDirection"]);+ setData(source, "Dewpoint", this->dewpoint(source));+ dataFields = this->pressure(source);+ setData(source, "Pressure", dataFields["pressure"]);+ setData(source, "Pressure Tendency", dataFields["pressureTendency"]);+ setData(source, "Visibility", this->visibility(source));+ setData(source, "Humidity", this->humidity(source));+ dataFields = this->wind(source);+ setData(source, "Wind Speed", dataFields["windSpeed"]);+ setData(source, "Wind Speed Unit", dataFields["windUnit"]);+ setData(source, "Wind Gust", dataFields["windGust"]);+ setData(source, "Wind Gust Unit", dataFields["windGustUnit"]);+ setData(source, "Wind Direction", dataFields["windDirection"]); - dataFields = this->regionalTemperatures(keyname);- setData(keyname, "Normal High", dataFields["normalHigh"]);- setData(keyname, "Normal Low", dataFields["normalLow"]);+ dataFields = this->regionalTemperatures(source);+ setData(source, "Normal High", dataFields["normalHigh"]);+ setData(source, "Normal Low", dataFields["normalLow"]); - // Check if UV index is available for the location- dataFields = this->uvIndex(keyname);- if (!dataFields["uvRating"].isEmpty()) {- setData(keyname, "UV Rating", dataFields["uvRating"]);- setData(keyname, "UV Index", dataFields["uvIndex"]);- }+ // Check if UV index is available for the location+ dataFields = this->uvIndex(source);+ if (!dataFields["uvRating"].isEmpty()) {+ setData(source, "UV Rating", dataFields["uvRating"]);+ setData(source, "UV Index", dataFields["uvIndex"]);+ } - dataFields = this->warnings(keyname);- // Check if we have warnings or watches- if (!dataFields["watch"].isEmpty()) {- fieldList = dataFields["watch"].split('|');- setData(keyname, "Watch Priority", fieldList[0]);- setData(keyname, "Watch Description", fieldList[1]);- setData(keyname, "Watch Info", fieldList[2]);- setData(keyname, "Watch Timestamp", fieldList[3]);- }- if (!dataFields["warning"].isEmpty()) {- fieldList = dataFields["warning"].split('|');- setData(keyname, "Warning Priority", fieldList[0]);- setData(keyname, "Warning Description", fieldList[1]);- setData(keyname, "Warning Info", fieldList[2]);- setData(keyname, "Warning Timestamp", fieldList[3]);- }+ dataFields = this->warnings(source);+ // Check if we have warnings or watches+ if (!dataFields["watch"].isEmpty()) {+ fieldList = dataFields["watch"].split('|');+ setData(source, "Watch Priority", fieldList[0]);+ setData(source, "Watch Description", fieldList[1]);+ setData(source, "Watch Info", fieldList[2]);+ setData(source, "Watch Timestamp", fieldList[3]);+ }+ if (!dataFields["warning"].isEmpty()) {+ fieldList = dataFields["warning"].split('|');+ setData(source, "Warning Priority", fieldList[0]);+ setData(source, "Warning Description", fieldList[1]);+ setData(source, "Warning Info", fieldList[2]);+ setData(source, "Warning Timestamp", fieldList[3]);+ } - forecastList = this->forecasts(keyname);- foreach(QString forecastItem, forecastList) {- fieldList = forecastItem.split('|');+ forecastList = this->forecasts(source);+ foreach(QString forecastItem, forecastList) {+ fieldList = forecastItem.split('|'); - if (d->m_useMetric) {- setData(keyname, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5") \- .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[5]));+ if (d->m_useMetric) {+ setData(source, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5") \+ .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[5])); - setData(keyname, QString("Long Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7|%8") \- .arg(fieldList[0]).arg(fieldList[2]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[6]) \- .arg(fieldList[7]).arg(fieldList[8]).arg(fieldList[9]));- } else {- setData(keyname, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5") \- .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[3] == "N/A" ? "N/A" : \- QString::number(d->m_formula.celsiusToF(fieldList[3].toFloat()), 'd', 0)) \- .arg(fieldList[4] == "N/A" ? "N/A" : QString::number(d->m_formula.celsiusToF(fieldList[4].toFloat()),'d',0)).arg(fieldList[5]));+ setData(source, QString("Long Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7|%8") \+ .arg(fieldList[0]).arg(fieldList[2]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[6]) \+ .arg(fieldList[7]).arg(fieldList[8]).arg(fieldList[9]));+ } else {+ setData(source, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5") \+ .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[3] == "N/A" ? "N/A" : \+ QString::number(d->m_formula.celsiusToF(fieldList[3].toFloat()), 'd', 0)) \+ .arg(fieldList[4] == "N/A" ? "N/A" : QString::number(d->m_formula.celsiusToF(fieldList[4].toFloat()),'d',0)).arg(fieldList[5])); - setData(keyname, QString("Long Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7|%8") \- .arg(fieldList[0]).arg(fieldList[2]).arg(fieldList[3] == "N/A" ? "N/A" : \- QString::number(d->m_formula.celsiusToF(fieldList[3].toFloat()),'d', 0)) \- .arg(fieldList[4] == "N/A" ? "N/A" : QString::number(d->m_formula.celsiusToF(fieldList[4].toFloat()),'d',0)).arg(fieldList[6]).arg(fieldList[7]) \- .arg(fieldList[8]).arg(fieldList[9]));+ setData(source, QString("Long Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7|%8") \+ .arg(fieldList[0]).arg(fieldList[2]).arg(fieldList[3] == "N/A" ? "N/A" : \+ QString::number(d->m_formula.celsiusToF(fieldList[3].toFloat()),'d', 0)) \+ .arg(fieldList[4] == "N/A" ? "N/A" : QString::number(d->m_formula.celsiusToF(fieldList[4].toFloat()),'d',0)).arg(fieldList[6]).arg(fieldList[7]) \+ .arg(fieldList[8]).arg(fieldList[9])); } i++; } - dataFields = this->yesterdayWeather(keyname);- setData(keyname, "Yesterday High", dataFields["prevHigh"]);- setData(keyname, "Yesterday Low", dataFields["prevLow"]);- setData(keyname, "Yesterday Precip Total", dataFields["prevPrecip"]);- setData(keyname, "Yesterday Precip Unit", dataFields["prevPrecipUnit"]);+ dataFields = this->yesterdayWeather(source);+ setData(source, "Yesterday High", dataFields["prevHigh"]);+ setData(source, "Yesterday Low", dataFields["prevLow"]);+ setData(source, "Yesterday Precip Total", dataFields["prevPrecip"]);+ setData(source, "Yesterday Precip Unit", dataFields["prevPrecipUnit"]); - dataFields = this->sunriseSet(keyname);- setData(keyname, "Sunrise At", dataFields["sunrise"]);- setData(keyname, "Sunset At", dataFields["sunset"]);+ dataFields = this->sunriseSet(source);+ setData(source, "Sunrise At", dataFields["sunrise"]);+ setData(source, "Sunset At", dataFields["sunset"]); - dataFields = this->moonriseSet(keyname);- setData(keyname, "Moonrise At", dataFields["moonrise"]);- setData(keyname, "Moonset At", dataFields["moonset"]);+ dataFields = this->moonriseSet(source);+ setData(source, "Moonrise At", dataFields["moonrise"]);+ setData(source, "Moonset At", dataFields["moonset"]); - dataFields = this->weatherRecords(keyname);- setData(keyname, "Record High Temperature", dataFields["recordHigh"]);- setData(keyname, "Record Low Temperature", dataFields["recordLow"]);- setData(keyname, "Record Rainfall", dataFields["recordRain"]);- setData(keyname, "Record Rainfall Unit", dataFields["recordRainUnit"]);- setData(keyname, "Record Snowfall", dataFields["recordSnow"]);- setData(keyname, "Record Snowfall Unit", dataFields["recordSnowUnit"]);+ dataFields = this->weatherRecords(source);+ setData(source, "Record High Temperature", dataFields["recordHigh"]);+ setData(source, "Record Low Temperature", dataFields["recordLow"]);+ setData(source, "Record Rainfall", dataFields["recordRain"]);+ setData(source, "Record Rainfall Unit", dataFields["recordRainUnit"]);+ setData(source, "Record Snowfall", dataFields["recordSnow"]);+ setData(source, "Record Snowfall Unit", dataFields["recordSnowUnit"]); - setData(keyname, "Credit", "Environment Canada");- i = 0;- }+ setData(source, "Credit", "Environment Canada"); } QString EnvCanadaIon::country(QString key)Index: ions/ion_envcan.h===================================================================--- ions/ion_envcan.h (revision 724674)+++ ions/ion_envcan.h (working copy)@@ -129,9 +129,9 @@ EnvCanadaIon(QObject *parent, const QVariantList &args); ~EnvCanadaIon(); void init(); // Setup the city location, fetching the correct URL name.- void fetch(); // Get the City XML data.- void updateData(void); // Sync data source with Applet+ bool updateIonSource(const QString& source); // Sync data source with Applet void option(int option, QVariant value);+ void updateWeather(const QString& source); protected slots: void setup_slotDataArrived(KIO::Job *, const QByteArray &);@@ -173,8 +173,8 @@ bool readXMLSetup(); // Load and parse the specific place(s)- void getXMLData();- bool readXMLData(QString key, QXmlStreamReader& xml);+ void getXMLData(const QString& source);+ bool readXMLData(const QString& source, QXmlStreamReader& xml); // Check if place specified is valid or not bool validLocation(QString key);Index: ions/ion.cpp===================================================================--- ions/ion.cpp (revision 724674)+++ ions/ion.cpp (working copy)@@ -24,12 +24,14 @@ { public: Private(IonInterface *i)- : ion(i) {}+ : ion(i),+ initialized(false)+ {} int ref; IonInterface *ion; bool valid;- QVector<QString> ionSource; // Array of this ions sources+ bool initialized; }; IonInterface::IonInterface(QObject *parent)@@ -62,29 +64,35 @@ return d->valid; } -// Set the Ions datasource name listing. Used by weather dataengine-void IonInterface::setSource(QString key)+bool IonInterface::sourceRequested(const QString &source) {- if (!d->ionSource.contains(key)) {- d->ionSource.append(key);+ setData(source, Plasma::DataEngine::Data());++ if (d->initialized) {+ this->updateSource(source); }++ return true; } -// Return an array of sources from a Ion-QVector<QString> IonInterface::ionSourceDict() const+bool IonInterface::updateSource(const QString& source) {- return d->ionSource;+ kDebug() << "SOURCE IS = " << source; + if (d->initialized) {+ this->updateIonSource(source);+ return true;+ }++ return false; } -// Deletes a datasource from the ion-void IonInterface::removeSource(QString key)+void IonInterface::setInitialized(bool initialized) {- QVector<QString>::iterator it;- for (it = d->ionSource.begin(); it != d->ionSource.end(); ++it) {- if (*it == key) {- kDebug() << "Going to remove: " << *it;- d->ionSource.erase(it);- break;- }- }+ d->initialized = initialized;++ if (d->initialized) {+ foreach (const QString &source, sources()) {+ updateSource(source);+ }+ } }Index: ions/ion.h===================================================================--- ions/ion.h (revision 724674)+++ ions/ion.h (working copy)@@ -51,16 +51,12 @@ * For example fetching the list of available cities or weather data sources should be fetched here. */ virtual void init(void) = 0;- /**- * Reimplement to do the fetching of weather data.- * This is being called just before calling updateData() - */- virtual void fetch(void) = 0; /** * Increment ion counter. This is used to watch if the ion is being used. */ void ref();+ /** * Decrement ion counter. */@@ -71,42 +67,42 @@ * @return true if the ion is being used, false otherwise */ bool isUsed() const;- + /** * Returns whether the ion is valid. Not used for now. * @return true if the ion is valid. */ bool isValid() const; + enum ionOptions { UNITS, TIMEFORMAT, WINDFORMAT }; /**- * Reimplement this to set the data to the engine by using setData() calls.- * You may have to force to call this method inside your ion everytime new data has been arrived from the fetching job.+ * Reimplement to set the wanted options for the ion such as unit and time, and wind speed formats. */- virtual void updateData(void) = 0;+ virtual void option(int option, QVariant value) = 0; - /**- * Returns the source array.- * @return Returns the array of source the ion has.- */- QVector<QString> ionSourceDict() const;- /**- * Set the datasource name to the array of sources- * @param key The name of the datasource- */- void setSource(QString key);+public slots:+ bool updateSource(const QString& source); +protected: /**- * Remove a datasource entry from the array- * @param key The name of the datasource- */- void removeSource(QString key);+ * Call this method to flush waiting source requests that may be pending+ * initialization+ *+ * @arg initialized whether or not the ion is currently ready to fetch data+ */+ void setInitialized(bool initialized); - enum ionOptions { UNITS, TIMEFORMAT, WINDFORMAT }; /**- * Reimplement to set the wanted options for the ion such as unit and time, and wind speed formats.- */- virtual void option(int option, QVariant value) = 0;+ * reimplemented from DataEngine+ */+ bool sourceRequested(const QString &name); + /**+ * Reimplement to fetch the data from the ion+ * + */+ virtual bool updateIonSource(const QString &name) = 0;+ private: class Private; Private* const d;Index: weatherengine.h===================================================================--- weatherengine.h (revision 724674)+++ weatherengine.h (working copy)@@ -48,16 +48,16 @@ protected: // dataEngine method - We use it to communicate to the Ion plugins to set the data sources- bool sourceRequested(const QString &);+ bool sourceRequested(const QString &source); protected slots: // SLOT: trigger to indicate new data is available from an Ion. There are two modes. // When using a timer no ion is specified, otherwise when loading an ion an ion is // specified.- void updateData(); void updated(const QString& source, Plasma::DataEngine::Data data); void newIonSource(const QString& source); void removeIonSource(const QString& source);+ bool updateSource(const QString& source); private: class Private;