add more spacing
[personal-kdebase.git] / workspace / plasma / dataengines / weather / ions / ion_envcan.cpp
blobc02be53b9e4636f7a2c5627ef2d51588f64014de
1 /***************************************************************************
2 * Copyright (C) 2007-2009 by Shawn Starr <shawn.starr@rogers.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
18 ***************************************************************************/
20 /* Ion for Environment Canada XML data */
22 #include "ion_envcan.h"
24 class EnvCanadaIon::Private : public QObject
26 public:
27 Private() {
28 m_url = 0;
30 ~Private() {
31 delete m_url;
34 private:
35 struct XMLMapInfo {
36 QString cityName;
37 QString territoryName;
38 QString cityCode;
39 QString sourceOptions;
42 public:
43 // Key dicts
44 QHash<QString, EnvCanadaIon::Private::XMLMapInfo> m_place;
45 QHash<QString, QString> m_locations;
46 QString m_code;
47 QString m_territory;
48 QString m_cityName;
50 // Weather information
51 QHash<QString, WeatherData> m_weatherData;
53 // Store KIO jobs
54 QMap<KJob *, QXmlStreamReader*> m_jobXml;
55 QMap<KJob *, QString> m_jobList;
56 QXmlStreamReader m_xmlSetup;
57 KUrl *m_url;
58 KIO::TransferJob *m_job;
60 QDateTime m_dateFormat;
64 // ctor, dtor
65 EnvCanadaIon::EnvCanadaIon(QObject *parent, const QVariantList &args)
66 : IonInterface(parent, args), d(new Private())
70 EnvCanadaIon::~EnvCanadaIon()
72 // Destroy each watch/warning stored in a QVector
73 foreach(const WeatherData &item, d->m_weatherData) {
74 foreach(WeatherData::WeatherEvent *warning, item.warnings) {
75 if (warning) {
76 delete warning;
80 foreach(WeatherData::WeatherEvent *watch, item.watches) {
81 if (watch) {
82 delete watch;
86 foreach(WeatherData::ForecastInfo *forecast, item.forecasts) {
87 if (forecast) {
88 delete forecast;
93 // Destroy dptr
94 delete d;
97 // Get the master list of locations to be parsed
98 void EnvCanadaIon::init()
100 // Get the real city XML URL so we can parse this
101 getXMLSetup();
104 QMap<QString, IonInterface::ConditionIcons> EnvCanadaIon::setupConditionIconMappings(void)
106 QMap<QString, ConditionIcons> conditionList;
108 // Explicit periods
109 conditionList["mainly sunny"] = FewCloudsDay;
110 conditionList["mainly clear"] = FewCloudsNight;
111 conditionList["sunny"] = ClearDay;
112 conditionList["clear"] = ClearNight;
114 // Available conditions
115 conditionList["blowing snow"] = Snow;
116 conditionList["cloudy"] = Overcast;
117 conditionList["distance precipitation"] = LightRain;
118 conditionList["drifting snow"] = Flurries;
119 conditionList["drizzle"] = LightRain;
120 conditionList["dust"] = NotAvailable;
121 conditionList["dust devils"] = NotAvailable;
122 conditionList["fog"] = Mist;
123 conditionList["fog bank near station"] = Mist;
124 conditionList["fog depositing ice"] = Mist;
125 conditionList["fog patches"] = Mist;
126 conditionList["freezing drizzle"] = FreezingDrizzle;
127 conditionList["freezing rain"] = FreezingRain;
128 conditionList["funnel cloud"] = NotAvailable;
129 conditionList["hail"] = Hail;
130 conditionList["haze"] = Haze;
131 conditionList["heavy blowing snow"] = Snow;
132 conditionList["heavy drifting snow"] = Snow;
133 conditionList["heavy drizzle"] = LightRain;
134 conditionList["heavy hail"] = Hail;
135 conditionList["heavy mixed rain and drizzle"] = LightRain;
136 conditionList["heavy mixed rain and snow shower"] = RainSnow;
137 conditionList["heavy rain"] = Rain;
138 conditionList["heavy rain and snow"] = RainSnow;
139 conditionList["heavy rainshower"] = Rain;
140 conditionList["heavy snow"] = Snow;
141 conditionList["heavy snow pellets"] = Snow;
142 conditionList["heavy snowshower"] = Snow;
143 conditionList["heavy thunderstorm with hail"] = Thunderstorm;
144 conditionList["heavy thunderstorm with rain"] = Thunderstorm;
145 conditionList["ice crystals"] = Flurries;
146 conditionList["ice pellets"] = Hail;
147 conditionList["increasing cloud"] = Overcast;
148 conditionList["light drizzle"] = LightRain;
149 conditionList["light freezing drizzle"] = FreezingRain;
150 conditionList["light freezing rain"] = FreezingRain;
151 conditionList["light rain"] = LightRain;
152 conditionList["light rainshower"] = LightRain;
153 conditionList["light snow"] = LightSnow;
154 conditionList["light snow pellets"] = LightSnow;
155 conditionList["light snowshower"] = Flurries;
156 conditionList["lightning visible"] = Thunderstorm;
157 conditionList["mist"] = Mist;
158 conditionList["mixed rain and drizzle"] = LightRain;
159 conditionList["mixed rain and snow shower"] = RainSnow;
160 conditionList["not reported"] = NotAvailable;
161 conditionList["rain"] = Rain;
162 conditionList["rain and snow"] = RainSnow;
163 conditionList["rainshower"] = LightRain;
164 conditionList["recent drizzle"] = LightRain;
165 conditionList["recent dust or sand storm"] = NotAvailable;
166 conditionList["recent fog"] = Mist;
167 conditionList["recent freezing precipitation"] = FreezingDrizzle;
168 conditionList["recent hail"] = Hail;
169 conditionList["recent rain"] = Rain;
170 conditionList["recent rain and snow"] = RainSnow;
171 conditionList["recent rainshower"] = Rain;
172 conditionList["recent snow"] = Snow;
173 conditionList["recent snowshower"] = Flurries;
174 conditionList["recent thunderstorm"] = Thunderstorm;
175 conditionList["recent thunderstorm with hail"] = Thunderstorm;
176 conditionList["recent thunderstorm with heavy hail"] = Thunderstorm;
177 conditionList["recent thunderstorm with heavy rain"] = Thunderstorm;
178 conditionList["recent thunderstorm with rain"] = Thunderstorm;
179 conditionList["sand or dust storm"] = NotAvailable;
180 conditionList["severe sand or dust storm"] = NotAvailable;
181 conditionList["shallow fog"] = Mist;
182 conditionList["smoke"] = NotAvailable;
183 conditionList["snow"] = Snow;
184 conditionList["snow crystals"] = Flurries;
185 conditionList["snow grains"] = Flurries;
186 conditionList["squalls"] = Snow;
187 conditionList["thunderstorm with hail"] = Thunderstorm;
188 conditionList["thunderstorm with rain"] = Thunderstorm;
189 conditionList["thunderstorm with sand or dust storm"] = Thunderstorm;
190 conditionList["thunderstorm without precipitation"] = Thunderstorm;
191 conditionList["tornado"] = NotAvailable;
192 return conditionList;
196 QMap<QString, IonInterface::ConditionIcons> EnvCanadaIon::setupForecastIconMappings(void)
198 QMap<QString, ConditionIcons> forecastList;
200 // Abbreviated forecast descriptions
201 forecastList["a few flurries"] = Flurries;
202 forecastList["a few flurries mixed with ice pellets"] = RainSnow;
203 forecastList["a few flurries or rain showers"] = RainSnow;
204 forecastList["a few flurries or thundershowers"] = RainSnow;
205 forecastList["a few rain showers or flurries"] = RainSnow;
206 forecastList["a few rain showers or wet flurries"] = RainSnow;
207 forecastList["a few showers"] = LightRain;
208 forecastList["a few showers or drizzle"] = LightRain;
209 forecastList["a few showers or thundershowers"] = Thunderstorm;
210 forecastList["a few showers or thunderstorms"] = Thunderstorm;
211 forecastList["a few thundershowers"] = Thunderstorm;
212 forecastList["a few thunderstorms"] = Thunderstorm;
213 forecastList["a few wet flurries"] = RainSnow;
214 forecastList["a few wet flurries or rain showers"] = RainSnow;
215 forecastList["a mix of sun and cloud"] = PartlyCloudyDay;
216 forecastList["cloudy with sunny periods"] = PartlyCloudyDay;
217 forecastList["sunny"] = ClearDay;
218 forecastList["blizzard"] = Snow;
219 forecastList["clear"] = ClearNight;
220 forecastList["cloudy"] = Overcast;
221 forecastList["drizzle"] = LightRain;
222 forecastList["drizzle mixed with freezing drizzle"] = FreezingDrizzle;
223 forecastList["drizzle mixed with rain"] = LightRain;
224 forecastList["drizzle or freezing drizzle"] = LightRain;
225 forecastList["drizzle or rain"] = LightRain;
226 forecastList["flurries"] = Flurries;
227 forecastList["flurries at times heavy"] = Flurries;
228 forecastList["flurries at times heavy or rain snowers"] = RainSnow;
229 forecastList["flurries mixed with ice pellets"] = FreezingRain;
230 forecastList["flurries or ice pellets"] = FreezingRain;
231 forecastList["flurries or rain showers"] = RainSnow;
232 forecastList["flurries or thundershowers"] = Flurries;
233 forecastList["fog"] = Mist;
234 forecastList["fog developing"] = Mist;
235 forecastList["fog dissipating"] = Mist;
236 forecastList["fog patches"] = Mist;
237 forecastList["freezing drizzle"] = FreezingDrizzle;
238 forecastList["freezing rain"] = FreezingRain;
239 forecastList["freezing rain mixed with rain"] = FreezingRain;
240 forecastList["freezing rain mixed with snow"] = FreezingRain;
241 forecastList["freezing rain or ice pellets"] = FreezingRain;
242 forecastList["freezing rain or rain"] = FreezingRain;
243 forecastList["freezing rain or snow"] = FreezingRain;
244 forecastList["ice fog"] = Mist;
245 forecastList["ice fog developing"] = Mist;
246 forecastList["ice fog dissipating"] = Mist;
247 forecastList["ice pellet"] = Hail;
248 forecastList["ice pellet mixed with freezing rain"] = Hail;
249 forecastList["ice pellet mixed with snow"] = Hail;
250 forecastList["ice pellet or snow"] = RainSnow;
251 forecastList["light snow"] = LightSnow;
252 forecastList["light snow and blizzard"] = LightSnow;
253 forecastList["light snow and blizzard and blowing snow"] = Snow;
254 forecastList["light snow and blowing snow"] = LightSnow;
255 forecastList["light snow mixed with freezing drizzle"] = FreezingDrizzle;
256 forecastList["light snow mixed with freezing rain"] = FreezingRain;
257 forecastList["light snow or ice pellets"] = LightSnow;
258 forecastList["light snow or rain"] = RainSnow;
259 forecastList["light wet snow"] = RainSnow;
260 forecastList["light wet snow or rain"] = RainSnow;
261 forecastList["local snow squalls"] = Snow;
262 forecastList["near blizzard"] = Snow;
263 forecastList["overcast"] = Overcast;
264 forecastList["increasing cloudiness"] = Overcast;
265 forecastList["increasing clouds"] = Overcast;
266 forecastList["periods of drizzle"] = LightRain;
267 forecastList["periods of drizzle mixed with freezing drizzle"] = FreezingDrizzle;
268 forecastList["periods of drizzle mixed with rain"] = LightRain;
269 forecastList["periods of drizzle or freezing drizzle"] = FreezingDrizzle;
270 forecastList["periods of drizzle or rain"] = LightRain;
271 forecastList["periods of freezing drizzle"] = FreezingDrizzle;
272 forecastList["periods of freezing drizzle or drizzle"] = FreezingDrizzle;
273 forecastList["periods of freezing drizzle or rain"] = FreezingDrizzle;
274 forecastList["periods of freezing rain"] = FreezingRain;
275 forecastList["periods of freezing rain mixed with ice pellets"] = FreezingRain;
276 forecastList["periods of freezing rain mixed with rain"] = FreezingRain;
277 forecastList["periods of freezing rain mixed with snow"] = FreezingRain;
278 forecastList["periods of freezing rain mixed with freezing drizzle"] = FreezingRain;
279 forecastList["periods of freezing rain or ice pellets"] = FreezingRain;
280 forecastList["periods of freezing rain or rain"] = FreezingRain;
281 forecastList["periods of freezing rain or snow"] = FreezingRain;
282 forecastList["periods of ice pellet"] = Hail;
283 forecastList["periods of ice pellet mixed with freezing rain"] = Hail;
284 forecastList["periods of ice pellet mixed with snow"] = Hail;
285 forecastList["periods of ice pellet or freezing rain"] = Hail;
286 forecastList["periods of ice pellet or snow"] = Hail;
287 forecastList["periods of light snow"] = LightSnow;
288 forecastList["periods of light snow and blizzard"] = Snow;
289 forecastList["periods of light snow and blizzard and blowing snow"] = Snow;
290 forecastList["periods of light snow and blowing snow"] = LightSnow;
291 forecastList["periods of light snow mixed with freezing drizzle"] = RainSnow;
292 forecastList["periods of light snow mixed with freezing rain"] = RainSnow;
293 forecastList["periods of light snow mixed with ice pelletS"] = LightSnow;
294 forecastList["periods of light snow mixed with rain"] = RainSnow;
295 forecastList["periods of light snow or freezing drizzle"] = RainSnow;
296 forecastList["periods of light snow or freezing rain"] = RainSnow;
297 forecastList["periods of light snow or ice pellets"] = LightSnow;
298 forecastList["periods of light snow or rain"] = RainSnow;
299 forecastList["periods of light wet snow"] = LightSnow;
300 forecastList["periods of light wet snow mixed with rain"] = RainSnow;
301 forecastList["periods of light wet snow or rain"] = RainSnow;
302 forecastList["periods of rain"] = Rain;
303 forecastList["periods of rain mixed with freezing rain"] = Rain;
304 forecastList["periods of rain mixed with snow"] = RainSnow;
305 forecastList["periods of rain or drizzle"] = Rain;
306 forecastList["periods of rain or freezing rain"] = Rain;
307 forecastList["periods of rain or thundershowers"] = Thunderstorm;
308 forecastList["periods of rain or thunderstorms"] = Thunderstorm;
309 forecastList["periods of rain or snow"] = RainSnow;
310 forecastList["periods of snow"] = Snow;
311 forecastList["periods of snow and blizzard"] = Snow;
312 forecastList["periods of snow and blizzard and blowing snow"] = Snow;
313 forecastList["periods of snow and blowing snow"] = Snow;
314 forecastList["periods of snow mixed with freezing drizzle"] = RainSnow;
315 forecastList["periods of snow mixed with freezing rain"] = RainSnow;
316 forecastList["periods of snow mixed with ice pellets"] = Snow;
317 forecastList["periods of snow mixed with rain"] = RainSnow;
318 forecastList["periods of snow or freezing drizzle"] = RainSnow;
319 forecastList["periods of snow or freezing rain"] = RainSnow;
320 forecastList["periods of snow or ice pellets"] = Snow;
321 forecastList["periods of snow or rain"] = RainSnow;
322 forecastList["periods of rain or snow"] = RainSnow;
323 forecastList["periods of wet snow"] = Snow;
324 forecastList["periods of wet snow mixed with rain"] = RainSnow;
325 forecastList["periods of wet snow or rain"] = RainSnow;
326 forecastList["rain"] = Rain;
327 forecastList["rain at times heavy"] = Rain;
328 forecastList["rain at times heavy mixed with freezing rain"] = FreezingRain;
329 forecastList["rain at times heavy mixed with snow"] = RainSnow;
330 forecastList["rain at times heavy or drizzle"] = Rain;
331 forecastList["rain at times heavy or freezing rain"] = Rain;
332 forecastList["rain at times heavy or snow"] = RainSnow;
333 forecastList["rain at times heavy or thundershowers"] = Thunderstorm;
334 forecastList["rain at times heavy or thunderstorms"] = Thunderstorm;
335 forecastList["rain mixed with freezing rain"] = FreezingRain;
336 forecastList["rain mixed with snow"] = RainSnow;
337 forecastList["rain or drizzle"] = Rain;
338 forecastList["rain or freezing rain"] = Rain;
339 forecastList["rain or snow"] = RainSnow;
340 forecastList["rain or thundershowers"] = Thunderstorm;
341 forecastList["rain or thunderstorms"] = Thunderstorm;
342 forecastList["rain showers or flurries"] = RainSnow;
343 forecastList["rain showers or wet flurries"] = RainSnow;
344 forecastList["showers"] = Showers;
345 forecastList["showers at times heavy"] = Showers;
346 forecastList["showers at times heavy or thundershowers"] = Thunderstorm;
347 forecastList["showers at times heavy or thunderstorms"] = Thunderstorm;
348 forecastList["showers or drizzle"] = Showers;
349 forecastList["showers or thundershowers"] = Showers;
350 forecastList["showers or thunderstorms"] = Showers;
351 forecastList["smoke"] = NotAvailable;
352 forecastList["snow"] = Snow;
353 forecastList["snow and blizzard"] = Snow;
354 forecastList["snow and blizzard and blowing snow"] = Snow;
355 forecastList["snow and blowing snow"] = Snow;
356 forecastList["snow at times heavy"] = Snow;
357 forecastList["snow at times heavy and blizzard"] = Snow;
358 forecastList["snow at times heavy and blowing snow"] = Snow;
359 forecastList["snow at times heavy mixed with freezing drizzle"] = RainSnow;
360 forecastList["snow at times heavy mixed with freezing rain"] = RainSnow;
361 forecastList["snow at times heavy mixed with ice pellets"] = Snow;
362 forecastList["snow at times heavy mixed with rain"] = RainSnow;
363 forecastList["snow at times heavy or freezing rain"] = RainSnow;
364 forecastList["snow at times heavy or ice pellets"] = Snow;
365 forecastList["snow at times heavy or rain"] = RainSnow;
366 forecastList["snow mixed with freezing drizzle"] = RainSnow;
367 forecastList["snow mixed with freezing rain"] = RainSnow;
368 forecastList["snow mixed with ice pellets"] = Snow;
369 forecastList["snow mixed with rain"] = RainSnow;
370 forecastList["snow or freezing drizzle"] = RainSnow;
371 forecastList["snow or freezing rain"] = RainSnow;
372 forecastList["snow or ice pellets"] = Snow;
373 forecastList["snow or rain"] = RainSnow;
374 forecastList["snow squalls"] = Snow;
375 forecastList["sunny"] = ClearDay;
376 forecastList["sunny with cloudy periods"] = PartlyCloudyDay;
377 forecastList["thunderstorms"] = Thunderstorm;
378 forecastList["thunderstorms and possible hail"] = Thunderstorm;
379 forecastList["wet flurries"] = Flurries;
380 forecastList["wet flurries at times heavy"] = Flurries;
381 forecastList["wet flurries at times heavy or rain snowers"] = RainSnow;
382 forecastList["wet flurries or rain showers"] = RainSnow;
383 forecastList["wet snow"] = Snow;
384 forecastList["wet snow at times heavy"] = Snow;
385 forecastList["wet snow at times heavy mixed with rain"] = RainSnow;
386 forecastList["wet snow mixed with rain"] = RainSnow;
387 forecastList["wet snow or rain"] = RainSnow;
388 forecastList["windy"] = NotAvailable;
390 forecastList["chance of drizzle mixed with freezing drizzle"] = LightRain;
391 forecastList["chance of flurries mixed with ice pellets"] = Flurries;
392 forecastList["chance of flurries or ice pellets"] = Flurries;
393 forecastList["chance of flurries or rain showers"] = RainSnow;
394 forecastList["chance of flurries or thundershowers"] = RainSnow;
395 forecastList["chance of freezing drizzle"] = FreezingDrizzle;
396 forecastList["chance of freezing rain"] = FreezingRain;
397 forecastList["chance of freezing rain mixed with snow"] = RainSnow;
398 forecastList["chance of freezing rain or rain"] = FreezingRain;
399 forecastList["chance of freezing rain or snow"] = RainSnow;
400 forecastList["chance of light snow and blowing snow"] = LightSnow;
401 forecastList["chance of light snow mixed with freezing drizzle"] = LightSnow;
402 forecastList["chance of light snow mixed with ice pellets"] = LightSnow;
403 forecastList["chance of light snow mixed with rain"] = RainSnow;
404 forecastList["chance of light snow or freezing rain"] = RainSnow;
405 forecastList["chance of light snow or ice pellets"] = LightSnow;
406 forecastList["chance of light snow or rain"] = RainSnow;
407 forecastList["chance of light wet snow"] = Snow;
408 forecastList["chance of rain"] = Rain;
409 forecastList["chance of rain at times heavy"] = Rain;
410 forecastList["chance of rain mixed with snow"] = RainSnow;
411 forecastList["chance of rain or drizzle"] = Rain;
412 forecastList["chance of rain or freezing rain"] = Rain;
413 forecastList["chance of rain or snow"] = RainSnow;
414 forecastList["chance of rain showers or flurries"] = RainSnow;
415 forecastList["chance of rain showers or wet flurries"] = RainSnow;
416 forecastList["chance of severe thunderstorms"] = Thunderstorm;
417 forecastList["chance of showers at times heavy"] = Rain;
418 forecastList["chance of showers at times heavy or thundershowers"] = Thunderstorm;
419 forecastList["chance of showers at times heavy or thunderstorms"] = Thunderstorm;
420 forecastList["chance of showers or thundershowers"] = Showers;
421 forecastList["chance of showers or thunderstorms"] = Thunderstorm;
422 forecastList["chance of snow"] = Snow;
423 forecastList["chance of snow and blizzard"] = Snow;
424 forecastList["chance of snow mixed with freezing drizzle"] = Snow;
425 forecastList["chance of snow mixed with freezing rain"] = RainSnow;
426 forecastList["chance of snow mixed with rain"] = RainSnow;
427 forecastList["chance of snow or rain"] = RainSnow;
428 forecastList["chance of snow squalls"] = Snow;
429 forecastList["chance of thundershowers"] = Thunderstorm;
430 forecastList["chance of thunderstorms"] = Thunderstorm;
431 forecastList["chance of thunderstorms and possible hail"] = Thunderstorm;
432 forecastList["chance of wet flurries"] = Flurries;
433 forecastList["chance of wet flurries at times heavy"] = Flurries;
434 forecastList["chance of wet flurries or rain showers"] = RainSnow;
435 forecastList["chance of wet snow"] = Snow;
436 forecastList["chance of wet snow mixed with rain"] = RainSnow;
437 forecastList["chance of wet snow or rain"] = RainSnow;
439 return forecastList;
442 QMap<QString, IonInterface::ConditionIcons> const& EnvCanadaIon::conditionIcons(void)
444 static QMap<QString, ConditionIcons> const condval = setupConditionIconMappings();
445 return condval;
448 QMap<QString, IonInterface::ConditionIcons> const& EnvCanadaIon::forecastIcons(void)
450 static QMap<QString, ConditionIcons> const foreval = setupForecastIconMappings();
451 return foreval;
454 QStringList EnvCanadaIon::validate(const QString& source) const
456 QStringList placeList;
457 QHash<QString, QString>::const_iterator it = d->m_locations.constBegin();
458 while (it != d->m_locations.constEnd()) {
459 if (it.value().toLower().contains(source.toLower())) {
460 placeList.append(QString("place|%1").arg(it.value().split('|')[1]));
462 ++it;
465 // Check if placeList is empty if so, return nothing.
466 if (placeList.isEmpty()) {
467 return QStringList();
469 placeList.sort();
470 return placeList;
473 // Get a specific Ion's data
474 bool EnvCanadaIon::updateIonSource(const QString& source)
476 // We expect the applet to send the source in the following tokenization:
477 // ionname|validate|place_name - Triggers validation of place
478 // ionname|weather|place_name - Triggers receiving weather of place
480 QStringList sourceAction = source.split('|');
482 // Guard: if the size of array is not 2 then we have bad data, return an error
483 if (sourceAction.size() < 2) {
484 setData(source, "validate", QString("envcan|timeout"));
485 return true;
488 if (sourceAction[1] == QString("validate")) {
489 QStringList result = validate(QString("%1|%2").arg(sourceAction[0]).arg(sourceAction[2]));
491 if (result.size() == 1) {
492 setData(source, "validate", QString("envcan|valid|single|%1").arg(result.join("|")));
493 return true;
494 } else if (result.size() > 1) {
495 setData(source, "validate", QString("envcan|valid|multiple|%1").arg(result.join("|")));
496 return true;
497 } else if (result.size() == 0) {
498 setData(source, "validate", QString("envcan|invalid|single|%1").arg(sourceAction[2]));
499 return true;
502 } else if (sourceAction[1] == QString("weather")) {
503 getXMLData(source);
504 return true;
506 return false;
509 // Parses city list and gets the correct city based on ID number
510 void EnvCanadaIon::getXMLSetup()
512 d->m_url = new KUrl("http://dd.weatheroffice.ec.gc.ca/EC_sites/xml/siteList.xml");
514 KIO::TransferJob *job = KIO::get(d->m_url->url(), KIO::NoReload, KIO::HideProgressInfo);
516 if (job) {
517 connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
518 SLOT(setup_slotDataArrived(KIO::Job *, const QByteArray &)));
519 connect(job, SIGNAL(result(KJob *)), this, SLOT(setup_slotJobFinished(KJob *)));
523 // Gets specific city XML data
524 void EnvCanadaIon::getXMLData(const QString& source)
526 KUrl url;
528 // Demunge source name for key only.
529 QString dataKey = source;
530 dataKey.remove("|weather");
531 url = "http://dd.weatheroffice.ec.gc.ca/EC_sites/xml/" + d->m_place[dataKey].territoryName + "/" + d->m_place[dataKey].cityCode + "_e.xml";
532 //url="file:///home/spstarr/Desktop/s0000649_e.xml";
534 if (d->m_place[dataKey].territoryName.isEmpty() && d->m_place[dataKey].cityCode.isEmpty()) {
535 setData(source, "validate", QString("envcan|timeout"));
536 return;
539 d->m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
540 d->m_jobXml.insert(d->m_job, new QXmlStreamReader);
541 d->m_jobList.insert(d->m_job, source);
543 if (d->m_job) {
544 connect(d->m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
545 SLOT(slotDataArrived(KIO::Job *, const QByteArray &)));
546 connect(d->m_job, SIGNAL(result(KJob *)), this, SLOT(slotJobFinished(KJob *)));
550 void EnvCanadaIon::setup_slotDataArrived(KIO::Job *job, const QByteArray &data)
552 Q_UNUSED(job)
554 if (data.isEmpty()) {
555 return;
558 // Send to xml.
559 d->m_xmlSetup.addData(data);
562 void EnvCanadaIon::slotDataArrived(KIO::Job *job, const QByteArray &data)
565 if (data.isEmpty() || !d->m_jobXml.contains(job)) {
566 return;
569 // Send to xml.
570 d->m_jobXml[job]->addData(data);
573 void EnvCanadaIon::slotJobFinished(KJob *job)
575 // Dual use method, if we're fetching location data to parse we need to do this first
576 setData(d->m_jobList[job], Data());
577 readXMLData(d->m_jobList[job], *d->m_jobXml[job]);
578 d->m_jobList.remove(job);
579 delete d->m_jobXml[job];
580 d->m_jobXml.remove(job);
583 void EnvCanadaIon::setup_slotJobFinished(KJob *job)
585 Q_UNUSED(job)
586 readXMLSetup();
587 setInitialized(true);
590 // Parse the city list and store into a QMap
591 bool EnvCanadaIon::readXMLSetup()
593 QString tmp;
594 while (!d->m_xmlSetup.atEnd()) {
595 d->m_xmlSetup.readNext();
597 if (d->m_xmlSetup.isStartElement()) {
599 // XML ID code to match filename
600 if (d->m_xmlSetup.name() == "site") {
601 d->m_code = d->m_xmlSetup.attributes().value("code").toString();
604 if (d->m_xmlSetup.name() == "nameEn") {
605 d->m_cityName = d->m_xmlSetup.readElementText(); // Name of cities
608 if (d->m_xmlSetup.name() == "provinceCode") {
609 d->m_territory = d->m_xmlSetup.readElementText(); // Provinces/Territory list
610 tmp = "envcan|" + d->m_cityName + ", " + d->m_territory; // Build the key name.
612 // Set the mappings
613 d->m_place[tmp].cityCode = d->m_code;
614 d->m_place[tmp].territoryName = d->m_territory;
615 d->m_place[tmp].cityName = d->m_cityName;
617 // Set the string list, we will use for the applet to display the available cities.
618 d->m_locations[tmp] = tmp;
623 return !d->m_xmlSetup.error();
626 WeatherData EnvCanadaIon::parseWeatherSite(WeatherData& data, QXmlStreamReader& xml)
628 while (!xml.atEnd()) {
629 xml.readNext();
631 if (xml.isStartElement()) {
632 if (xml.name() == "license") {
633 xml.readElementText();
634 } else if (xml.name() == "location") {
635 parseLocations(data, xml);
636 } else if (xml.name() == "warnings") {
637 // Cleanup warning list on update
638 data.warnings.clear();
639 data.watches.clear();
640 parseWarnings(data, xml);
641 } else if (xml.name() == "currentConditions") {
642 parseConditions(data, xml);
643 } else if (xml.name() == "forecastGroup") {
644 // Clean up forecast list on update
645 data.forecasts.clear();
646 parseWeatherForecast(data, xml);
647 } else if (xml.name() == "yesterdayConditions") {
648 parseYesterdayWeather(data, xml);
649 } else if (xml.name() == "riseSet") {
650 parseAstronomicals(data, xml);
651 } else if (xml.name() == "almanac") {
652 parseWeatherRecords(data, xml);
653 } else {
654 parseUnknownElement(xml);
658 return data;
661 // Parse Weather data main loop, from here we have to decend into each tag pair
662 bool EnvCanadaIon::readXMLData(const QString& source, QXmlStreamReader& xml)
664 WeatherData data;
665 data.comforttemp = "N/A";
666 data.recordHigh = 0.0;
667 data.recordLow = 0.0;
669 QString dataKey = source;
670 dataKey.remove("|weather");
671 data.shortTerritoryName = d->m_place[dataKey].territoryName;
672 while (!xml.atEnd()) {
673 xml.readNext();
675 if (xml.isEndElement()) {
676 break;
679 if (xml.isStartElement()) {
680 if (xml.name() == "siteData") {
681 data = parseWeatherSite(data, xml);
682 } else {
683 parseUnknownElement(xml);
688 d->m_weatherData[source] = data;
689 updateWeather(source);
690 return !xml.error();
693 void EnvCanadaIon::parseDateTime(WeatherData& data, QXmlStreamReader& xml, WeatherData::WeatherEvent *event)
696 Q_ASSERT(xml.isStartElement() && xml.name() == "dateTime");
698 // What kind of date info is this?
699 QString dateType = xml.attributes().value("name").toString();
700 QString dateZone = xml.attributes().value("zone").toString();
702 QString selectTimeStamp;
704 while (!xml.atEnd()) {
705 xml.readNext();
707 if (xml.isEndElement()) {
708 break;
711 if (xml.isStartElement()) {
712 if (dateType == "xmlCreation") {
713 return;
715 if (dateZone == "UTC") {
716 return;
718 if (xml.name() == "year") {
719 xml.readElementText();
720 } else if (xml.name() == "month") {
721 xml.readElementText();
722 } else if (xml.name() == "day") {
723 xml.readElementText();
724 } else if (xml.name() == "hour")
725 xml.readElementText();
726 else if (xml.name() == "minute")
727 xml.readElementText();
728 else if (xml.name() == "timeStamp")
729 selectTimeStamp = xml.readElementText();
730 else if (xml.name() == "textSummary") {
731 if (dateType == "eventIssue") {
732 if (event) {
733 event->timestamp = xml.readElementText();
735 } else if (dateType == "observation") {
736 xml.readElementText();
737 d->m_dateFormat = QDateTime::fromString(selectTimeStamp, "yyyyMMddHHmmss");
738 data.obsTimestamp = d->m_dateFormat.toString("dd.MM.yyyy @ hh:mm ap");
739 data.iconPeriodHour = d->m_dateFormat.toString("HH").toInt();
740 data.iconPeriodAP = d->m_dateFormat.toString("ap");
741 } else if (dateType == "forecastIssue") {
742 data.forecastTimestamp = xml.readElementText();
743 } else if (dateType == "sunrise") {
744 data.sunriseTimestamp = xml.readElementText();
745 } else if (dateType == "sunset") {
746 data.sunsetTimestamp = xml.readElementText();
747 } else if (dateType == "moonrise") {
748 data.moonriseTimestamp = xml.readElementText();
749 } else if (dateType == "moonset") {
750 data.moonsetTimestamp = xml.readElementText();
757 void EnvCanadaIon::parseLocations(WeatherData& data, QXmlStreamReader& xml)
759 Q_ASSERT(xml.isStartElement() && xml.name() == "location");
761 while (!xml.atEnd()) {
762 xml.readNext();
764 if (xml.isEndElement()) {
765 break;
768 if (xml.isStartElement()) {
769 if (xml.name() == "country") {
770 data.countryName = xml.readElementText();
771 } else if (xml.name() == "province" || xml.name() == "territory") {
772 data.longTerritoryName = xml.readElementText();
773 } else if (xml.name() == "name") {
774 data.cityName = xml.readElementText();
775 } else if (xml.name() == "region") {
776 data.regionName = xml.readElementText();
777 } else {
778 parseUnknownElement(xml);
784 void EnvCanadaIon::parseWindInfo(WeatherData& data, QXmlStreamReader& xml)
786 Q_ASSERT(xml.isStartElement() && xml.name() == "wind");
788 while (!xml.atEnd()) {
789 xml.readNext();
791 if (xml.isEndElement()) {
792 break;
795 if (xml.isStartElement()) {
796 if (xml.name() == "speed") {
797 data.windSpeed = xml.readElementText();
798 } else if (xml.name() == "gust") {
799 data.windGust = xml.readElementText();
800 } else if (xml.name() == "direction") {
801 data.windDirection = xml.readElementText();
802 } else if (xml.name() == "bearing") {
803 data.windDegrees = xml.attributes().value("degrees").toString();
804 } else {
805 parseUnknownElement(xml);
811 void EnvCanadaIon::parseConditions(WeatherData& data, QXmlStreamReader& xml)
814 Q_ASSERT(xml.isStartElement() && xml.name() == "currentConditions");
815 data.temperature = "N/A";
816 data.dewpoint = "N/A";
817 data.condition = "N/A";
818 data.comforttemp = "N/A";
819 data.stationID = "N/A";
820 data.pressure = 0.0;
821 data.pressureTendency = "N/A";
822 data.visibility = 0;
823 data.humidity = "N/A";
824 data.windSpeed = "N/A";
825 data.windGust = "N/A";
827 while (!xml.atEnd()) {
828 xml.readNext();
830 if (xml.isEndElement() && xml.name() == "currentConditions")
831 break;
833 if (xml.isStartElement()) {
834 if (xml.name() == "station") {
835 data.stationID = xml.attributes().value("code").toString();
836 } else if (xml.name() == "dateTime") {
837 parseDateTime(data, xml);
838 } else if (xml.name() == "condition") {
839 data.condition = xml.readElementText();
840 } else if (xml.name() == "temperature") {
841 data.temperature = xml.readElementText();
842 } else if (xml.name() == "dewpoint") {
843 data.dewpoint = xml.readElementText();
844 } else if (xml.name() == "humidex" || xml.name() == "windChill") {
845 data.comforttemp = xml.readElementText();
846 } else if (xml.name() == "pressure") {
847 data.pressureTendency = xml.attributes().value("tendency").toString();
848 if (data.pressureTendency.isEmpty()) {
849 data.pressureTendency = "steady";
851 data.pressure = xml.readElementText().toFloat();
852 } else if (xml.name() == "visibility") {
853 data.visibility = xml.readElementText().toFloat();
854 } else if (xml.name() == "relativeHumidity") {
855 data.humidity = xml.readElementText();
856 } else if (xml.name() == "wind") {
857 parseWindInfo(data, xml);
859 //} else {
860 // parseUnknownElement(xml);
864 if (data.temperature.isEmpty()) {
865 data.temperature = "N/A";
869 void EnvCanadaIon::parseWarnings(WeatherData &data, QXmlStreamReader& xml)
871 WeatherData::WeatherEvent *watch = new WeatherData::WeatherEvent;
872 WeatherData::WeatherEvent *warning = new WeatherData::WeatherEvent;
874 Q_ASSERT(xml.isStartElement() && xml.name() == "warnings");
875 QString eventURL = xml.attributes().value("url").toString();
876 int flag = 0;
878 while (!xml.atEnd()) {
879 xml.readNext();
881 if (xml.isEndElement() && xml.name() == "warnings") {
882 break;
885 if (xml.isStartElement()) {
886 if (xml.name() == "dateTime") {
887 if (flag == 1) {
888 parseDateTime(data, xml, watch);
890 if (flag == 2) {
891 parseDateTime(data, xml, warning);
894 if (!warning->timestamp.isEmpty() && !warning->url.isEmpty()) {
895 data.warnings.append(warning);
896 warning = new WeatherData::WeatherEvent;
898 if (!watch->timestamp.isEmpty() && !watch->url.isEmpty()) {
899 data.watches.append(watch);
900 watch = new WeatherData::WeatherEvent;
903 } else if (xml.name() == "event") {
904 // Append new event to list.
905 QString eventType = xml.attributes().value("type").toString();
906 if (eventType == "watch") {
907 watch->url = eventURL;
908 watch->type = eventType;
909 watch->priority = xml.attributes().value("priority").toString();
910 watch->description = xml.attributes().value("description").toString();
911 flag = 1;
914 if (eventType == "warning") {
915 warning->url = eventURL;
916 warning->type = eventType;
917 warning->priority = xml.attributes().value("priority").toString();
918 warning->description = xml.attributes().value("description").toString();
919 flag = 2;
921 } else {
922 if (xml.name() != "dateTime") {
923 parseUnknownElement(xml);
928 delete watch;
929 delete warning;
933 void EnvCanadaIon::parseWeatherForecast(WeatherData& data, QXmlStreamReader& xml)
935 WeatherData::ForecastInfo* forecast = new WeatherData::ForecastInfo;
936 Q_ASSERT(xml.isStartElement() && xml.name() == "forecastGroup");
938 while (!xml.atEnd()) {
939 xml.readNext();
941 if (xml.isEndElement() && xml.name() == "forecastGroup") {
942 break;
945 if (xml.isStartElement()) {
946 if (xml.name() == "dateTime") {
947 parseDateTime(data, xml);
948 } else if (xml.name() == "regionalNormals") {
949 parseRegionalNormals(data, xml);
950 } else if (xml.name() == "forecast") {
951 parseForecast(data, xml, forecast);
952 forecast = new WeatherData::ForecastInfo;
953 } else {
954 parseUnknownElement(xml);
958 delete forecast;
961 void EnvCanadaIon::parseRegionalNormals(WeatherData& data, QXmlStreamReader& xml)
963 Q_ASSERT(xml.isStartElement() && xml.name() == "regionalNormals");
965 while (!xml.atEnd()) {
966 xml.readNext();
968 if (xml.isEndElement()) {
969 break;
972 if (xml.isStartElement()) {
973 if (xml.name() == "textSummary") {
974 xml.readElementText();
975 } else if (xml.name() == "temperature" && xml.attributes().value("class") == "high") {
976 data.normalHigh = xml.readElementText();
977 } else if (xml.name() == "temperature" && xml.attributes().value("class") == "low") {
978 data.normalLow = xml.readElementText();
984 void EnvCanadaIon::parseForecast(WeatherData& data, QXmlStreamReader& xml, WeatherData::ForecastInfo *forecast)
987 Q_ASSERT(xml.isStartElement() && xml.name() == "forecast");
989 while (!xml.atEnd()) {
990 xml.readNext();
992 if (xml.isEndElement() && xml.name() == "forecast") {
993 data.forecasts.append(forecast);
994 break;
997 if (xml.isStartElement()) {
998 if (xml.name() == "period") {
999 forecast->forecastPeriod = xml.attributes().value("textForecastName").toString();
1000 } else if (xml.name() == "textSummary") {
1001 forecast->forecastSummary = xml.readElementText();
1002 } else if (xml.name() == "abbreviatedForecast") {
1003 parseShortForecast(forecast, xml);
1004 } else if (xml.name() == "temperatures") {
1005 parseForecastTemperatures(forecast, xml);
1006 } else if (xml.name() == "winds") {
1007 parseWindForecast(forecast, xml);
1008 } else if (xml.name() == "precipitation") {
1009 parsePrecipitationForecast(forecast, xml);
1010 } else if (xml.name() == "uv") {
1011 data.UVRating = xml.attributes().value("category").toString();
1012 parseUVIndex(data, xml);
1013 // else if (xml.name() == "frost") { FIXME: Wait until winter to see what this looks like.
1014 // parseFrost(xml, forecast);
1015 } else {
1016 if (xml.name() != "forecast") {
1017 parseUnknownElement(xml);
1024 void EnvCanadaIon::parseShortForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1026 Q_ASSERT(xml.isStartElement() && xml.name() == "abbreviatedForecast");
1028 QString shortText;
1030 while (!xml.atEnd()) {
1031 xml.readNext();
1033 if (xml.isEndElement() && xml.name() == "abbreviatedForecast") {
1034 break;
1037 if (xml.isStartElement()) {
1038 if (xml.name() == "pop") {
1039 forecast->popPrecent = xml.readElementText();
1041 if (xml.name() == "textSummary") {
1042 shortText = xml.readElementText();
1043 QMap<QString, ConditionIcons> forecastList;
1044 forecastList = forecastIcons();
1045 if ((forecast->forecastPeriod == "tonight") || (forecast->forecastPeriod.contains("night"))) {
1046 forecastList["a few clouds"] = FewCloudsNight;
1047 forecastList["cloudy periods"] = PartlyCloudyNight;
1048 forecastList["chance of drizzle mixed with rain"] = ChanceShowersNight;
1049 forecastList["chance of drizzle"] = ChanceShowersNight;
1050 forecastList["chance of drizzle or rain"] = ChanceShowersNight;
1051 forecastList["chance of flurries"] = ChanceSnowNight;
1052 forecastList["chance of light snow"] = ChanceSnowNight;
1053 forecastList["chance of flurries at times heavy"] = ChanceSnowNight;
1054 forecastList["chance of showers or drizzle"] = ChanceShowersNight;
1055 forecastList["chance of showers"] = ChanceShowersNight;
1056 forecastList["clearing"] = ClearNight;
1057 } else {
1058 forecastList["a few clouds"] = FewCloudsDay;
1059 forecastList["cloudy periods"] = PartlyCloudyDay;
1060 forecastList["chance of drizzle mixed with rain"] = ChanceShowersDay;
1061 forecastList["chance of drizzle"] = ChanceShowersDay;
1062 forecastList["chance of drizzle or rain"] = ChanceShowersDay;
1063 forecastList["chance of flurries"] = ChanceSnowDay;
1064 forecastList["chance of light snow"] = ChanceSnowDay;
1065 forecastList["chance of flurries at times heavy"] = ChanceSnowDay;
1066 forecastList["chance of showers or drizzle"] = ChanceShowersDay;
1067 forecastList["chance of showers"] = ChanceShowersDay;
1068 forecastList["clearing"] = ClearDay;
1070 forecast->shortForecast = shortText;
1071 forecast->iconName = getWeatherIcon(forecastList, shortText.toLower());
1077 void EnvCanadaIon::parseUVIndex(WeatherData& data, QXmlStreamReader& xml)
1079 Q_ASSERT(xml.isStartElement() && xml.name() == "uv");
1081 while (!xml.atEnd()) {
1082 xml.readNext();
1084 if (xml.isEndElement() && xml.name() == "uv") {
1085 break;
1088 if (xml.isStartElement()) {
1089 if (xml.name() == "index") {
1090 data.UVIndex = xml.readElementText();
1092 if (xml.name() == "textSummary") {
1093 xml.readElementText();
1099 void EnvCanadaIon::parseForecastTemperatures(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1101 Q_ASSERT(xml.isStartElement() && xml.name() == "temperatures");
1103 while (!xml.atEnd()) {
1104 xml.readNext();
1106 if (xml.isEndElement() && xml.name() == "temperatures") {
1107 break;
1110 if (xml.isStartElement()) {
1111 if (xml.name() == "temperature" && xml.attributes().value("class") == "low") {
1112 forecast->forecastTempLow = xml.readElementText();
1113 } else if (xml.name() == "temperature" && xml.attributes().value("class") == "high") {
1114 forecast->forecastTempHigh = xml.readElementText();
1115 } else if (xml.name() == "textSummary") {
1116 xml.readElementText();
1122 void EnvCanadaIon::parsePrecipitationForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1124 Q_ASSERT(xml.isStartElement() && xml.name() == "precipitation");
1126 while (!xml.atEnd()) {
1127 xml.readNext();
1129 if (xml.isEndElement() && xml.name() == "precipitation") {
1130 break;
1133 if (xml.isStartElement()) {
1134 //kDebug() << "parsePrecipitationForecast() ====> TAG: " << xml.name().toString();
1135 if (xml.name() == "textSummary") {
1136 forecast->precipForecast = xml.readElementText();
1137 } else if (xml.name() == "precipType") {
1138 forecast->precipType = xml.readElementText();
1139 } else if (xml.name() == "accumulation") {
1140 parsePrecipTotals(forecast, xml);
1146 void EnvCanadaIon::parsePrecipTotals(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1148 Q_ASSERT(xml.isStartElement() && xml.name() == "accumulation");
1150 while (!xml.atEnd()) {
1151 xml.readNext();
1153 if (xml.isEndElement() && xml.name() == "accumulation") {
1154 break;
1157 if (xml.name() == "name") {
1158 xml.readElementText();
1159 } else if (xml.name() == "amount") {
1160 forecast->precipTotalExpected = xml.readElementText();
1165 void EnvCanadaIon::parseWindForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1167 Q_ASSERT(xml.isStartElement() && xml.name() == "winds");
1169 while (!xml.atEnd()) {
1170 xml.readNext();
1172 if (xml.isEndElement() && xml.name() == "winds") {
1173 break;
1176 if (xml.isStartElement()) {
1177 if (xml.name() == "textSummary") {
1178 forecast->windForecast = xml.readElementText();
1179 } else {
1180 if (xml.name() != "winds") {
1181 parseUnknownElement(xml);
1188 void EnvCanadaIon::parseYesterdayWeather(WeatherData& data, QXmlStreamReader& xml)
1190 Q_ASSERT(xml.isStartElement() && xml.name() == "yesterdayConditions");
1192 while (!xml.atEnd()) {
1193 xml.readNext();
1195 if (xml.isEndElement()) {
1196 break;
1199 if (xml.isStartElement()) {
1200 if (xml.name() == "temperature" && xml.attributes().value("class") == "high") {
1201 data.prevHigh = xml.readElementText();
1202 } else if (xml.name() == "temperature" && xml.attributes().value("class") == "low") {
1203 data.prevLow = xml.readElementText();
1204 } else if (xml.name() == "precip") {
1205 data.prevPrecipType = xml.attributes().value("units").toString();
1206 if (data.prevPrecipType.isEmpty()) {
1207 data.prevPrecipType = QString::number(WeatherUtils::NoUnit);
1209 data.prevPrecipTotal = xml.readElementText();
1215 void EnvCanadaIon::parseWeatherRecords(WeatherData& data, QXmlStreamReader& xml)
1217 Q_ASSERT(xml.isStartElement() && xml.name() == "almanac");
1219 while (!xml.atEnd()) {
1220 xml.readNext();
1222 if (xml.isEndElement() && xml.name() == "almanac") {
1223 break;
1226 if (xml.isStartElement()) {
1227 if (xml.name() == "temperature" && xml.attributes().value("class") == "extremeMax") {
1228 data.recordHigh = xml.readElementText().toFloat();
1229 } else if (xml.name() == "temperature" && xml.attributes().value("class") == "extremeMin") {
1230 data.recordLow = xml.readElementText().toFloat();
1231 } else if (xml.name() == "precipitation" && xml.attributes().value("class") == "extremeRainfall") {
1232 data.recordRain = xml.readElementText().toFloat();
1233 } else if (xml.name() == "precipitation" && xml.attributes().value("class") == "extremeSnowfall") {
1234 data.recordSnow = xml.readElementText().toFloat();
1240 void EnvCanadaIon::parseAstronomicals(WeatherData& data, QXmlStreamReader& xml)
1242 Q_ASSERT(xml.isStartElement() && xml.name() == "riseSet");
1244 while (!xml.atEnd()) {
1245 xml.readNext();
1247 if (xml.isEndElement() && xml.name() == "riseSet") {
1248 break;
1251 if (xml.isStartElement()) {
1252 if (xml.name() == "disclaimer") {
1253 xml.readElementText();
1254 } else if (xml.name() == "dateTime") {
1255 parseDateTime(data, xml);
1261 // handle when no XML tag is found
1262 void EnvCanadaIon::parseUnknownElement(QXmlStreamReader& xml)
1265 while (!xml.atEnd()) {
1266 xml.readNext();
1268 if (xml.isEndElement()) {
1269 break;
1272 if (xml.isStartElement()) {
1273 parseUnknownElement(xml);
1278 void EnvCanadaIon::updateWeather(const QString& source)
1280 QMap<QString, QString> dataFields;
1281 QStringList fieldList;
1282 QVector<QString> forecastList;
1283 int i = 0;
1285 setData(source, "Country", country(source));
1286 setData(source, "Place", QString("%1, %2").arg(city(source)).arg(territory(source)));
1287 setData(source, "Region", region(source));
1288 setData(source, "Station", station(source));
1290 // Real weather - Current conditions
1291 setData(source, "Observation Period", observationTime(source));
1292 setData(source, "Current Conditions", condition(source));
1294 // Tell applet which icon to use for conditions and provide mapping for condition type to the icons to display
1295 QMap<QString, ConditionIcons> conditionList;
1296 conditionList = conditionIcons();
1298 if ((periodHour(source) >= 0 && periodHour(source) < 6) || (periodHour(source) >= 18)) {
1299 conditionList["decreasing cloud"] = FewCloudsNight;
1300 conditionList["mostly cloudy"] = PartlyCloudyNight;
1301 conditionList["partly cloudy"] = PartlyCloudyNight;
1302 conditionList["fair"] = FewCloudsNight;
1303 } else {
1304 conditionList["decreasing cloud"] = FewCloudsDay;
1305 conditionList["mostly cloudy"] = PartlyCloudyDay;
1306 conditionList["partly cloudy"] = PartlyCloudyDay;
1307 conditionList["fair"] = FewCloudsDay;
1310 setData(source, "Condition Icon", getWeatherIcon(conditionList, condition(source)));
1312 dataFields = temperature(source);
1313 setData(source, "Temperature", dataFields["temperature"]);
1315 // Do we have a comfort temperature? if so display it
1316 if (dataFields["comfortTemperature"] != "N/A" && !dataFields["comfortTemperature"].isEmpty()) {
1317 if (dataFields["comfortTemperature"].toFloat() <= 0) {
1318 setData(source, "Windchill", QString("%1").arg(dataFields["comfortTemperature"]));
1319 setData(source, "Humidex", "N/A");
1320 } else {
1321 setData(source, "Humidex", QString("%1").arg(dataFields["comfortTemperature"]));
1322 setData(source, "Windchill", "N/A");
1324 } else {
1325 setData(source, "Windchill", "N/A");
1326 setData(source, "Humidex", "N/A");
1329 setData(source, "Temperature Unit", dataFields["temperatureUnit"]);
1331 setData(source, "Dewpoint", dewpoint(source));
1332 if (dewpoint(source) != "N/A") {
1333 setData(source, "Dewpoint Unit", dataFields["temperatureUnit"]);
1336 dataFields = pressure(source);
1337 setData(source, "Pressure", dataFields["pressure"]);
1339 if (dataFields["pressure"] != "N/A") {
1340 setData(source, "Pressure Tendency", dataFields["pressureTendency"]);
1341 setData(source, "Pressure Unit", dataFields["pressureUnit"]);
1344 dataFields = visibility(source);
1345 setData(source, "Visibility", dataFields["visibility"]);
1346 if (dataFields["visibility"] != "N/A") {
1347 setData(source, "Visibility Unit", dataFields["visibilityUnit"]);
1350 setData(source, "Humidity", humidity(source));
1352 dataFields = wind(source);
1353 setData(source, "Wind Speed", dataFields["windSpeed"]);
1354 if (dataFields["windSpeed"] != "N/A") {
1355 setData(source, "Wind Speed Unit", dataFields["windUnit"]);
1357 setData(source, "Wind Gust", dataFields["windGust"]);
1358 setData(source, "Wind Direction", dataFields["windDirection"]);
1359 setData(source, "Wind Degrees", dataFields["windDegrees"]);
1360 setData(source, "Wind Gust Unit", dataFields["windGustUnit"]);
1362 dataFields = regionalTemperatures(source);
1363 setData(source, "Normal High", dataFields["normalHigh"]);
1364 setData(source, "Normal Low", dataFields["normalLow"]);
1365 if (dataFields["normalHigh"] != "N/A" && dataFields["normalLow"] != "N/A") {
1366 setData(source, "Regional Temperature Unit", dataFields["regionalTempUnit"]);
1369 // Check if UV index is available for the location
1370 dataFields = uvIndex(source);
1371 setData(source, "UV Index", dataFields["uvIndex"]);
1372 if (dataFields["uvIndex"] != "N/A") {
1373 setData(source, "UV Rating", dataFields["uvRating"]);
1376 dataFields = watches(source);
1378 // Set number of forecasts per day/night supported
1379 setData(source, QString("Total Watches Issued"), d->m_weatherData[source].watches.size());
1381 // Check if we have warnings or watches
1382 for (int i = 0; i < d->m_weatherData[source].watches.size(); i++) {
1383 fieldList = dataFields[QString("watch %1").arg(i)].split('|');
1384 setData(source, QString("Watch Priority %1").arg(i), fieldList[0]);
1385 setData(source, QString("Watch Description %1").arg(i), fieldList[1]);
1386 setData(source, QString("Watch Info %1").arg(i), fieldList[2]);
1387 setData(source, QString("Watch Timestamp %1").arg(i), fieldList[3]);
1390 dataFields = warnings(source);
1392 setData(source, QString("Total Warnings Issued"), d->m_weatherData[source].warnings.size());
1394 for (int k = 0; k < d->m_weatherData[source].warnings.size(); k++) {
1395 fieldList = dataFields[QString("warning %1").arg(k)].split('|');
1396 setData(source, QString("Warning Priority %1").arg(k), fieldList[0]);
1397 setData(source, QString("Warning Description %1").arg(k), fieldList[1]);
1398 setData(source, QString("Warning Info %1").arg(k), fieldList[2]);
1399 setData(source, QString("Warning Timestamp %1").arg(k), fieldList[3]);
1402 forecastList = forecasts(source);
1404 // Set number of forecasts per day/night supported
1405 setData(source, QString("Total Weather Days"), d->m_weatherData[source].forecasts.size());
1407 foreach(const QString &forecastItem, forecastList) {
1408 fieldList = forecastItem.split('|');
1410 setData(source, QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6") \
1411 .arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[2]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[5]));
1414 setData(source, QString("Long Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7|%8") \
1415 .arg(fieldList[0]).arg(fieldList[2]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[6]) \
1416 .arg(fieldList[7]).arg(fieldList[8]).arg(fieldList[9]));
1418 i++;
1421 dataFields = yesterdayWeather(source);
1422 setData(source, "Yesterday High", dataFields["prevHigh"]);
1423 setData(source, "Yesterday Low", dataFields["prevLow"]);
1425 if (dataFields["prevHigh"] != "N/A" && dataFields["prevLow"] != "N/A") {
1426 setData(source , "Yesterday Temperature Unit", dataFields["yesterdayTempUnit"]);
1429 setData(source, "Yesterday Precip Total", dataFields["prevPrecip"]);
1430 setData(source, "Yesterday Precip Unit", dataFields["prevPrecipUnit"]);
1432 dataFields = sunriseSet(source);
1433 setData(source, "Sunrise At", dataFields["sunrise"]);
1434 setData(source, "Sunset At", dataFields["sunset"]);
1436 dataFields = moonriseSet(source);
1437 setData(source, "Moonrise At", dataFields["moonrise"]);
1438 setData(source, "Moonset At", dataFields["moonset"]);
1440 dataFields = weatherRecords(source);
1441 setData(source, "Record High Temperature", dataFields["recordHigh"]);
1442 setData(source, "Record Low Temperature", dataFields["recordLow"]);
1443 if (dataFields["recordHigh"] != "N/A" && dataFields["recordLow"] != "N/A") {
1444 setData(source, "Record Temperature Unit", dataFields["recordTempUnit"]);
1447 setData(source, "Record Rainfall", dataFields["recordRain"]);
1448 setData(source, "Record Rainfall Unit", dataFields["recordRainUnit"]);
1449 setData(source, "Record Snowfall", dataFields["recordSnow"]);
1450 setData(source, "Record Snowfall Unit", dataFields["recordSnowUnit"]);
1452 setData(source, "Credit", "Meteorological data is provided by Environment Canada");
1455 QString EnvCanadaIon::country(const QString& source)
1457 return d->m_weatherData[source].countryName;
1459 QString EnvCanadaIon::territory(const QString& source)
1461 return d->m_weatherData[source].shortTerritoryName;
1463 QString EnvCanadaIon::city(const QString& source)
1465 return d->m_weatherData[source].cityName;
1467 QString EnvCanadaIon::region(const QString& source)
1469 return d->m_weatherData[source].regionName;
1471 QString EnvCanadaIon::station(const QString& source)
1473 if (!d->m_weatherData[source].stationID.isEmpty()) {
1474 return d->m_weatherData[source].stationID.toUpper();
1477 return QString("N/A");
1480 QString EnvCanadaIon::observationTime(const QString& source)
1482 return d->m_weatherData[source].obsTimestamp;
1486 bool EnvCanadaIon::night(const QString& source)
1488 if (d->m_weatherData[source].iconPeriodAP == "pm") {
1489 return true;
1491 return false;
1495 int EnvCanadaIon::periodHour(const QString& source)
1497 return d->m_weatherData[source].iconPeriodHour;
1500 QString EnvCanadaIon::condition(const QString& source)
1502 if (d->m_weatherData[source].condition.isEmpty()) {
1503 d->m_weatherData[source].condition = "N/A";
1505 return d->m_weatherData[source].condition;
1508 QString EnvCanadaIon::dewpoint(const QString& source)
1510 if (!d->m_weatherData[source].dewpoint.isEmpty()) {
1511 return QString::number(d->m_weatherData[source].dewpoint.toFloat(), 'f', 1);
1513 return QString("N/A");
1516 QString EnvCanadaIon::humidity(const QString& source)
1518 if (!d->m_weatherData[source].humidity.isEmpty()) {
1519 return QString("%1%").arg(d->m_weatherData[source].humidity);
1521 return QString("N/A");
1524 QMap<QString, QString> EnvCanadaIon::visibility(const QString& source)
1526 QMap<QString, QString> visibilityInfo;
1528 if (!d->m_weatherData[source].visibility == 0) {
1529 visibilityInfo.insert("visibility", QString::number(d->m_weatherData[source].visibility, 'f', 1));
1530 visibilityInfo.insert("visibilityUnit", QString::number(WeatherUtils::Kilometers));
1531 } else {
1532 visibilityInfo.insert("visibility", "N/A");
1534 return visibilityInfo;
1537 QMap<QString, QString> EnvCanadaIon::temperature(const QString& source)
1539 QMap<QString, QString> temperatureInfo;
1540 if (!d->m_weatherData[source].temperature.isEmpty()) {
1541 temperatureInfo.insert("temperature", QString::number(d->m_weatherData[source].temperature.toFloat(), 'f', 1));
1544 if (d->m_weatherData[source].temperature == "N/A") {
1545 temperatureInfo.insert("temperature", "N/A");
1548 temperatureInfo.insert("temperatureUnit", QString::number(WeatherUtils::Celsius));
1549 temperatureInfo.insert("comfortTemperature", "N/A");
1551 if (d->m_weatherData[source].comforttemp != "N/A") {
1552 temperatureInfo.insert("comfortTemperature", d->m_weatherData[source].comforttemp);
1554 return temperatureInfo;
1557 QMap<QString, QString> EnvCanadaIon::watches(const QString& source)
1559 QMap<QString, QString> watchData;
1560 QString watchType;
1561 for (int i = 0; i < d->m_weatherData[source].watches.size(); ++i) {
1562 watchType = QString("watch %1").arg(i);
1563 watchData[watchType] = QString("%1|%2|%3|%4").arg(d->m_weatherData[source].watches[i]->priority) \
1564 .arg(d->m_weatherData[source].watches[i]->description) \
1565 .arg(d->m_weatherData[source].watches[i]->url) \
1566 .arg(d->m_weatherData[source].watches[i]->timestamp);
1568 return watchData;
1571 QMap<QString, QString> EnvCanadaIon::warnings(const QString& source)
1573 QMap<QString, QString> warningData;
1574 QString warnType;
1575 for (int i = 0; i < d->m_weatherData[source].warnings.size(); ++i) {
1576 warnType = QString("warning %1").arg(i);
1577 warningData[warnType] = QString("%1|%2|%3|%4").arg(d->m_weatherData[source].warnings[i]->priority) \
1578 .arg(d->m_weatherData[source].warnings[i]->description) \
1579 .arg(d->m_weatherData[source].warnings[i]->url) \
1580 .arg(d->m_weatherData[source].warnings[i]->timestamp);
1582 return warningData;
1585 QVector<QString> EnvCanadaIon::forecasts(const QString& source)
1587 QVector<QString> forecastData;
1589 // Do some checks for empty data
1590 for (int i = 0; i < d->m_weatherData[source].forecasts.size(); ++i) {
1591 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.isEmpty()) {
1592 d->m_weatherData[source].forecasts[i]->forecastPeriod = "N/A";
1594 if (d->m_weatherData[source].forecasts[i]->shortForecast.isEmpty()) {
1595 d->m_weatherData[source].forecasts[i]->shortForecast = "N/A";
1597 if (d->m_weatherData[source].forecasts[i]->iconName.isEmpty()) {
1598 d->m_weatherData[source].forecasts[i]->iconName = "N/A";
1600 if (d->m_weatherData[source].forecasts[i]->forecastSummary.isEmpty()) {
1601 d->m_weatherData[source].forecasts[i]->forecastSummary = "N/A";
1603 if (d->m_weatherData[source].forecasts[i]->forecastTempHigh.isEmpty()) {
1604 d->m_weatherData[source].forecasts[i]->forecastTempHigh = "N/A";
1606 if (d->m_weatherData[source].forecasts[i]->forecastTempLow.isEmpty()) {
1607 d->m_weatherData[source].forecasts[i]->forecastTempLow = "N/A";
1609 if (d->m_weatherData[source].forecasts[i]->popPrecent.isEmpty()) {
1610 d->m_weatherData[source].forecasts[i]->popPrecent = "N/A";
1612 if (d->m_weatherData[source].forecasts[i]->windForecast.isEmpty()) {
1613 d->m_weatherData[source].forecasts[i]->windForecast = "N/A";
1615 if (d->m_weatherData[source].forecasts[i]->precipForecast.isEmpty()) {
1616 d->m_weatherData[source].forecasts[i]->precipForecast = "N/A";
1618 if (d->m_weatherData[source].forecasts[i]->precipType.isEmpty()) {
1619 d->m_weatherData[source].forecasts[i]->precipType = "N/A";
1621 if (d->m_weatherData[source].forecasts[i]->precipTotalExpected.isEmpty()) {
1622 d->m_weatherData[source].forecasts[i]->precipTotalExpected = "N/A";
1626 for (int i = 0; i < d->m_weatherData[source].forecasts.size(); ++i) {
1627 // We need to shortform the day/night strings.
1628 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Tonight")) {
1629 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Tonight", "nite");
1632 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("night")) {
1633 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("night", "nt");
1636 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Saturday")) {
1637 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Saturday", "Sat");
1640 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Sunday")) {
1641 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Sunday", "Sun");
1644 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Monday")) {
1645 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Monday", "Mon");
1648 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Tuesday")) {
1649 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Tuesday", "Tue");
1652 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Wednesday")) {
1653 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Wednesday", "Wed");
1656 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Thursday")) {
1657 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Thursday", "Thu");
1659 if (d->m_weatherData[source].forecasts[i]->forecastPeriod.contains("Friday")) {
1660 d->m_weatherData[source].forecasts[i]->forecastPeriod.replace("Friday", "Fri");
1663 forecastData.append(QString("%1|%2|%3|%4|%5|%6") \
1664 .arg(d->m_weatherData[source].forecasts[i]->forecastPeriod) \
1665 .arg(d->m_weatherData[source].forecasts[i]->iconName) \
1666 .arg(d->m_weatherData[source].forecasts[i]->shortForecast) \
1667 .arg(d->m_weatherData[source].forecasts[i]->forecastTempHigh) \
1668 .arg(d->m_weatherData[source].forecasts[i]->forecastTempLow) \
1669 .arg(d->m_weatherData[source].forecasts[i]->popPrecent));
1671 return forecastData;
1674 QMap<QString, QString> EnvCanadaIon::pressure(const QString& source)
1676 QMap<QString, QString> pressureInfo;
1678 if (d->m_weatherData[source].pressure == 0) {
1679 pressureInfo.insert("pressure", "N/A");
1680 return pressureInfo;
1681 } else {
1682 pressureInfo.insert("pressure", QString::number(d->m_weatherData[source].pressure, 'f', 1));
1683 pressureInfo.insert("pressureUnit", QString::number(WeatherUtils::Kilopascals));
1684 pressureInfo.insert("pressureTendency", d->m_weatherData[source].pressureTendency);
1686 return pressureInfo;
1689 QMap<QString, QString> EnvCanadaIon::wind(const QString& source)
1691 QMap<QString, QString> windInfo;
1693 // May not have any winds
1694 if (d->m_weatherData[source].windSpeed.isEmpty()) {
1695 windInfo.insert("windSpeed", "N/A");
1696 windInfo.insert("windUnit", QString::number(WeatherUtils::NoUnit));
1697 } else if (d->m_weatherData[source].windSpeed.toInt() == 0) {
1698 windInfo.insert("windSpeed", "Calm");
1699 windInfo.insert("windUnit", QString::number(WeatherUtils::NoUnit));
1700 } else {
1701 windInfo.insert("windSpeed", QString::number(d->m_weatherData[source].windSpeed.toInt()));
1702 windInfo.insert("windUnit", QString::number(WeatherUtils::KilometersAnHour));
1705 // May not always have gusty winds
1706 if (d->m_weatherData[source].windGust.isEmpty()) {
1707 windInfo.insert("windGust", "N/A");
1708 windInfo.insert("windGustUnit", QString::number(WeatherUtils::NoUnit));
1709 } else {
1710 windInfo.insert("windGust", QString::number(d->m_weatherData[source].windGust.toInt()));
1711 windInfo.insert("windGustUnit", QString::number(WeatherUtils::KilometersAnHour));
1714 if (d->m_weatherData[source].windDirection.isEmpty() && d->m_weatherData[source].windSpeed.isEmpty()) {
1715 windInfo.insert("windDirection", "N/A");
1716 windInfo.insert("windDegrees", "N/A");
1717 } else if (d->m_weatherData[source].windSpeed.toInt() == 0) {
1718 windInfo.insert("windDirection", "VR");
1719 } else {
1720 windInfo.insert("windDirection", d->m_weatherData[source].windDirection);
1721 windInfo.insert("windDegrees", d->m_weatherData[source].windDegrees);
1723 return windInfo;
1726 QMap<QString, QString> EnvCanadaIon::uvIndex(const QString& source)
1728 QMap<QString, QString> uvInfo;
1730 if (d->m_weatherData[source].UVRating.isEmpty()) {
1731 uvInfo.insert("uvRating", "N/A");
1732 } else {
1733 uvInfo.insert("uvRating", d->m_weatherData[source].UVRating);
1736 if (d->m_weatherData[source].UVIndex.isEmpty()) {
1737 uvInfo.insert("uvIndex", "N/A");
1738 } else {
1739 uvInfo.insert("uvIndex", d->m_weatherData[source].UVIndex);
1742 return uvInfo;
1745 QMap<QString, QString> EnvCanadaIon::regionalTemperatures(const QString& source)
1747 QMap<QString, QString> regionalTempInfo;
1749 if (d->m_weatherData[source].normalHigh.isEmpty()) {
1750 regionalTempInfo.insert("normalHigh", "N/A");
1751 } else {
1752 regionalTempInfo.insert("normalHigh", d->m_weatherData[source].normalHigh);
1755 if (d->m_weatherData[source].normalLow.isEmpty()) {
1756 regionalTempInfo.insert("normalLow", "N/A");
1757 } else {
1758 regionalTempInfo.insert("normalLow", d->m_weatherData[source].normalLow);
1761 regionalTempInfo.insert("regionalTempUnit", QString::number(WeatherUtils::Celsius));
1762 return regionalTempInfo;
1765 QMap<QString, QString> EnvCanadaIon::yesterdayWeather(const QString& source)
1767 QMap<QString, QString> yesterdayInfo;
1769 if (d->m_weatherData[source].prevHigh.isEmpty()) {
1770 yesterdayInfo.insert("prevHigh", "N/A");
1771 } else {
1772 yesterdayInfo.insert("prevHigh", d->m_weatherData[source].prevHigh);
1775 if (d->m_weatherData[source].prevLow.isEmpty()) {
1776 yesterdayInfo.insert("prevLow", "N/A");
1777 } else {
1778 yesterdayInfo.insert("prevLow", d->m_weatherData[source].prevLow);
1781 yesterdayInfo.insert("yesterdayTempUnit", QString::number(WeatherUtils::Celsius));
1783 if (d->m_weatherData[source].prevPrecipTotal == "Trace") {
1784 yesterdayInfo.insert("prevPrecip", "Trace");
1785 return yesterdayInfo;
1788 if (d->m_weatherData[source].prevPrecipTotal.isEmpty()) {
1789 yesterdayInfo.insert("prevPrecip", "N/A");
1790 } else {
1791 yesterdayInfo.insert("prevPrecipTotal", d->m_weatherData[source].prevPrecipTotal);
1792 if (d->m_weatherData[source].prevPrecipType == "mm") {
1793 yesterdayInfo.insert("prevPrecipUnit", QString::number(WeatherUtils::Millimeters));
1794 } else if (d->m_weatherData[source].prevPrecipType == "cm") {
1795 yesterdayInfo.insert("prevPrecipUnit", QString::number(WeatherUtils::Centimeters));
1796 } else {
1797 yesterdayInfo.insert("prevPrecipUnit", QString::number(WeatherUtils::NoUnit));
1801 return yesterdayInfo;
1804 QMap<QString, QString> EnvCanadaIon::sunriseSet(const QString& source)
1806 QMap<QString, QString> sunInfo;
1808 if (d->m_weatherData[source].sunriseTimestamp.isEmpty()) {
1809 sunInfo.insert("sunrise", "N/A");
1810 } else {
1811 sunInfo.insert("sunrise", d->m_weatherData[source].sunriseTimestamp);
1814 if (d->m_weatherData[source].sunsetTimestamp.isEmpty()) {
1815 sunInfo.insert("sunset", "N/A");
1816 } else {
1817 sunInfo.insert("sunset", d->m_weatherData[source].sunsetTimestamp);
1820 return sunInfo;
1823 QMap<QString, QString> EnvCanadaIon::moonriseSet(const QString& source)
1825 QMap<QString, QString> moonInfo;
1827 if (d->m_weatherData[source].moonriseTimestamp.isEmpty()) {
1828 moonInfo.insert("moonrise", "N/A");
1829 } else {
1830 moonInfo.insert("moonrise", d->m_weatherData[source].moonriseTimestamp);
1833 if (d->m_weatherData[source].moonsetTimestamp.isEmpty()) {
1834 moonInfo.insert("moonset", "N/A");
1835 } else {
1836 moonInfo.insert("moonset", d->m_weatherData[source].moonsetTimestamp);
1839 return moonInfo;
1842 QMap<QString, QString> EnvCanadaIon::weatherRecords(const QString& source)
1844 QMap<QString, QString> recordInfo;
1846 if (d->m_weatherData[source].recordHigh == 0) {
1847 recordInfo.insert("recordHigh", "N/A");
1848 } else {
1849 recordInfo.insert("recordHigh", QString("%1").arg(d->m_weatherData[source].recordHigh));
1852 if (d->m_weatherData[source].recordLow == 0) {
1853 recordInfo.insert("recordLow", "N/A");
1854 } else {
1855 recordInfo.insert("recordLow", QString("%1").arg(d->m_weatherData[source].recordLow));
1858 recordInfo.insert("recordTempUnit", QString::number(WeatherUtils::Celsius));
1860 if (d->m_weatherData[source].recordRain == 0) {
1861 recordInfo.insert("recordRain", "N/A");
1862 } else {
1863 recordInfo.insert("recordRain", QString("%1").arg(d->m_weatherData[source].recordRain));
1864 recordInfo.insert("recordRainUnit", QString::number(WeatherUtils::Millimeters));
1867 if (d->m_weatherData[source].recordSnow == 0) {
1868 recordInfo.insert("recordSnow", "N/A");
1869 } else {
1870 recordInfo.insert("recordSnow", QString("%1").arg(d->m_weatherData[source].recordSnow));
1871 recordInfo.insert("recordSnowUnit", QString::number(WeatherUtils::Centimeters));
1874 return recordInfo;
1877 #include "ion_envcan.moc"