1
/***************************************************************************
2
* Copyright (C) 2007-2009 by Shawn Starr <shawn.starr@rogers.com> *
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. *
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. *
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"
25
#include <KUnitConversion/Converter>
26
#include <Solid/Networking>
27
#include <Plasma/DataContainer>
31
EnvCanadaIon::EnvCanadaIon(QObject *parent, const QVariantList &args)
32
: IonInterface(parent, args)
36
void EnvCanadaIon::deleteForecasts()
38
QMutableHashIterator<QString, WeatherData> it(m_weatherData);
39
while (it.hasNext()) {
41
WeatherData &item = it.value();
42
qDeleteAll(item.warnings);
43
item.warnings.clear();
45
qDeleteAll(item.watches);
48
qDeleteAll(item.forecasts);
49
item.forecasts.clear();
53
void EnvCanadaIon::reset()
57
m_sourcesToReset = sources();
61
EnvCanadaIon::~EnvCanadaIon()
63
// Destroy each watch/warning stored in a QVector
67
// Get the master list of locations to be parsed
68
void EnvCanadaIon::init()
70
// Get the real city XML URL so we can parse this
72
m_timeEngine = dataEngine("time");
75
QMap<QString, IonInterface::ConditionIcons> EnvCanadaIon::setupConditionIconMappings(void) const
77
QMap<QString, ConditionIcons> conditionList;
80
conditionList["mainly sunny"] = FewCloudsDay;
81
conditionList["mainly clear"] = FewCloudsNight;
82
conditionList["sunny"] = ClearDay;
83
conditionList["clear"] = ClearNight;
85
// Available conditions
86
conditionList["blowing snow"] = Snow;
87
conditionList["cloudy"] = Overcast;
88
conditionList["distant precipitation"] = LightRain;
89
conditionList["drifting snow"] = Flurries;
90
conditionList["drizzle"] = LightRain;
91
conditionList["dust"] = NotAvailable;
92
conditionList["dust devils"] = NotAvailable;
93
conditionList["fog"] = Mist;
94
conditionList["fog bank near station"] = Mist;
95
conditionList["fog depositing ice"] = Mist;
96
conditionList["fog patches"] = Mist;
97
conditionList["freezing drizzle"] = FreezingDrizzle;
98
conditionList["freezing rain"] = FreezingRain;
99
conditionList["funnel cloud"] = NotAvailable;
100
conditionList["hail"] = Hail;
101
conditionList["haze"] = Haze;
102
conditionList["heavy blowing snow"] = Snow;
103
conditionList["heavy drifting snow"] = Snow;
104
conditionList["heavy drizzle"] = LightRain;
105
conditionList["heavy hail"] = Hail;
106
conditionList["heavy mixed rain and drizzle"] = LightRain;
107
conditionList["heavy mixed rain and snow shower"] = RainSnow;
108
conditionList["heavy rain"] = Rain;
109
conditionList["heavy rain and snow"] = RainSnow;
110
conditionList["heavy rainshower"] = Rain;
111
conditionList["heavy snow"] = Snow;
112
conditionList["heavy snow pellets"] = Snow;
113
conditionList["heavy snowshower"] = Snow;
114
conditionList["heavy thunderstorm with hail"] = Thunderstorm;
115
conditionList["heavy thunderstorm with rain"] = Thunderstorm;
116
conditionList["ice crystals"] = Flurries;
117
conditionList["ice pellets"] = Hail;
118
conditionList["increasing cloud"] = Overcast;
119
conditionList["light drizzle"] = LightRain;
120
conditionList["light freezing drizzle"] = FreezingRain;
121
conditionList["light freezing rain"] = FreezingRain;
122
conditionList["light rain"] = LightRain;
123
conditionList["light rainshower"] = LightRain;
124
conditionList["light snow"] = LightSnow;
125
conditionList["light snow pellets"] = LightSnow;
126
conditionList["light snowshower"] = Flurries;
127
conditionList["lightning visible"] = Thunderstorm;
128
conditionList["mist"] = Mist;
129
conditionList["mixed rain and drizzle"] = LightRain;
130
conditionList["mixed rain and snow shower"] = RainSnow;
131
conditionList["not reported"] = NotAvailable;
132
conditionList["rain"] = Rain;
133
conditionList["rain and snow"] = RainSnow;
134
conditionList["rainshower"] = LightRain;
135
conditionList["recent drizzle"] = LightRain;
136
conditionList["recent dust or sand storm"] = NotAvailable;
137
conditionList["recent fog"] = Mist;
138
conditionList["recent freezing precipitation"] = FreezingDrizzle;
139
conditionList["recent hail"] = Hail;
140
conditionList["recent rain"] = Rain;
141
conditionList["recent rain and snow"] = RainSnow;
142
conditionList["recent rainshower"] = Rain;
143
conditionList["recent snow"] = Snow;
144
conditionList["recent snowshower"] = Flurries;
145
conditionList["recent thunderstorm"] = Thunderstorm;
146
conditionList["recent thunderstorm with hail"] = Thunderstorm;
147
conditionList["recent thunderstorm with heavy hail"] = Thunderstorm;
148
conditionList["recent thunderstorm with heavy rain"] = Thunderstorm;
149
conditionList["recent thunderstorm with rain"] = Thunderstorm;
150
conditionList["sand or dust storm"] = NotAvailable;
151
conditionList["severe sand or dust storm"] = NotAvailable;
152
conditionList["shallow fog"] = Mist;
153
conditionList["smoke"] = NotAvailable;
154
conditionList["snow"] = Snow;
155
conditionList["snow crystals"] = Flurries;
156
conditionList["snow grains"] = Flurries;
157
conditionList["squalls"] = Snow;
158
conditionList["thunderstorm with hail"] = Thunderstorm;
159
conditionList["thunderstorm with rain"] = Thunderstorm;
160
conditionList["thunderstorm with sand or dust storm"] = Thunderstorm;
161
conditionList["thunderstorm without precipitation"] = Thunderstorm;
162
conditionList["tornado"] = NotAvailable;
163
return conditionList;
167
QMap<QString, IonInterface::ConditionIcons> EnvCanadaIon::setupForecastIconMappings(void) const
169
QMap<QString, ConditionIcons> forecastList;
171
// Abbreviated forecast descriptions
172
forecastList["a few flurries"] = Flurries;
173
forecastList["a few flurries mixed with ice pellets"] = RainSnow;
174
forecastList["a few flurries or rain showers"] = RainSnow;
175
forecastList["a few flurries or thundershowers"] = RainSnow;
176
forecastList["a few rain showers or flurries"] = RainSnow;
177
forecastList["a few rain showers or wet flurries"] = RainSnow;
178
forecastList["a few showers"] = LightRain;
179
forecastList["a few showers or drizzle"] = LightRain;
180
forecastList["a few showers or thundershowers"] = Thunderstorm;
181
forecastList["a few showers or thunderstorms"] = Thunderstorm;
182
forecastList["a few thundershowers"] = Thunderstorm;
183
forecastList["a few thunderstorms"] = Thunderstorm;
184
forecastList["a few wet flurries"] = RainSnow;
185
forecastList["a few wet flurries or rain showers"] = RainSnow;
186
forecastList["a mix of sun and cloud"] = PartlyCloudyDay;
187
forecastList["cloudy with sunny periods"] = PartlyCloudyDay;
188
forecastList["sunny"] = ClearDay;
189
forecastList["blizzard"] = Snow;
190
forecastList["clear"] = ClearNight;
191
forecastList["cloudy"] = Overcast;
192
forecastList["drizzle"] = LightRain;
193
forecastList["drizzle mixed with freezing drizzle"] = FreezingDrizzle;
194
forecastList["drizzle mixed with rain"] = LightRain;
195
forecastList["drizzle or freezing drizzle"] = LightRain;
196
forecastList["drizzle or rain"] = LightRain;
197
forecastList["flurries"] = Flurries;
198
forecastList["flurries at times heavy"] = Flurries;
199
forecastList["flurries at times heavy or rain snowers"] = RainSnow;
200
forecastList["flurries mixed with ice pellets"] = FreezingRain;
201
forecastList["flurries or ice pellets"] = FreezingRain;
202
forecastList["flurries or rain showers"] = RainSnow;
203
forecastList["flurries or thundershowers"] = Flurries;
204
forecastList["fog"] = Mist;
205
forecastList["fog developing"] = Mist;
206
forecastList["fog dissipating"] = Mist;
207
forecastList["fog patches"] = Mist;
208
forecastList["freezing drizzle"] = FreezingDrizzle;
209
forecastList["freezing rain"] = FreezingRain;
210
forecastList["freezing rain mixed with rain"] = FreezingRain;
211
forecastList["freezing rain mixed with snow"] = FreezingRain;
212
forecastList["freezing rain or ice pellets"] = FreezingRain;
213
forecastList["freezing rain or rain"] = FreezingRain;
214
forecastList["freezing rain or snow"] = FreezingRain;
215
forecastList["ice fog"] = Mist;
216
forecastList["ice fog developing"] = Mist;
217
forecastList["ice fog dissipating"] = Mist;
218
forecastList["ice pellet"] = Hail;
219
forecastList["ice pellet mixed with freezing rain"] = Hail;
220
forecastList["ice pellet mixed with snow"] = Hail;
221
forecastList["ice pellet or snow"] = RainSnow;
222
forecastList["light snow"] = LightSnow;
223
forecastList["light snow and blizzard"] = LightSnow;
224
forecastList["light snow and blizzard and blowing snow"] = Snow;
225
forecastList["light snow and blowing snow"] = LightSnow;
226
forecastList["light snow mixed with freezing drizzle"] = FreezingDrizzle;
227
forecastList["light snow mixed with freezing rain"] = FreezingRain;
228
forecastList["light snow or ice pellets"] = LightSnow;
229
forecastList["light snow or rain"] = RainSnow;
230
forecastList["light wet snow"] = RainSnow;
231
forecastList["light wet snow or rain"] = RainSnow;
232
forecastList["local snow squalls"] = Snow;
233
forecastList["near blizzard"] = Snow;
234
forecastList["overcast"] = Overcast;
235
forecastList["increasing cloudiness"] = Overcast;
236
forecastList["increasing clouds"] = Overcast;
237
forecastList["periods of drizzle"] = LightRain;
238
forecastList["periods of drizzle mixed with freezing drizzle"] = FreezingDrizzle;
239
forecastList["periods of drizzle mixed with rain"] = LightRain;
240
forecastList["periods of drizzle or freezing drizzle"] = FreezingDrizzle;
241
forecastList["periods of drizzle or rain"] = LightRain;
242
forecastList["periods of freezing drizzle"] = FreezingDrizzle;
243
forecastList["periods of freezing drizzle or drizzle"] = FreezingDrizzle;
244
forecastList["periods of freezing drizzle or rain"] = FreezingDrizzle;
245
forecastList["periods of freezing rain"] = FreezingRain;
246
forecastList["periods of freezing rain mixed with ice pellets"] = FreezingRain;
247
forecastList["periods of freezing rain mixed with rain"] = FreezingRain;
248
forecastList["periods of freezing rain mixed with snow"] = FreezingRain;
249
forecastList["periods of freezing rain mixed with freezing drizzle"] = FreezingRain;
250
forecastList["periods of freezing rain or ice pellets"] = FreezingRain;
251
forecastList["periods of freezing rain or rain"] = FreezingRain;
252
forecastList["periods of freezing rain or snow"] = FreezingRain;
253
forecastList["periods of ice pellet"] = Hail;
254
forecastList["periods of ice pellet mixed with freezing rain"] = Hail;
255
forecastList["periods of ice pellet mixed with snow"] = Hail;
256
forecastList["periods of ice pellet or freezing rain"] = Hail;
257
forecastList["periods of ice pellet or snow"] = Hail;
258
forecastList["periods of light snow"] = LightSnow;
259
forecastList["periods of light snow and blizzard"] = Snow;
260
forecastList["periods of light snow and blizzard and blowing snow"] = Snow;
261
forecastList["periods of light snow and blowing snow"] = LightSnow;
262
forecastList["periods of light snow mixed with freezing drizzle"] = RainSnow;
263
forecastList["periods of light snow mixed with freezing rain"] = RainSnow;
264
forecastList["periods of light snow mixed with ice pelletS"] = LightSnow;
265
forecastList["periods of light snow mixed with rain"] = RainSnow;
266
forecastList["periods of light snow or freezing drizzle"] = RainSnow;
267
forecastList["periods of light snow or freezing rain"] = RainSnow;
268
forecastList["periods of light snow or ice pellets"] = LightSnow;
269
forecastList["periods of light snow or rain"] = RainSnow;
270
forecastList["periods of light wet snow"] = LightSnow;
271
forecastList["periods of light wet snow mixed with rain"] = RainSnow;
272
forecastList["periods of light wet snow or rain"] = RainSnow;
273
forecastList["periods of rain"] = Rain;
274
forecastList["periods of rain mixed with freezing rain"] = Rain;
275
forecastList["periods of rain mixed with snow"] = RainSnow;
276
forecastList["periods of rain or drizzle"] = Rain;
277
forecastList["periods of rain or freezing rain"] = Rain;
278
forecastList["periods of rain or thundershowers"] = Showers;
279
forecastList["periods of rain or thunderstorms"] = Thunderstorm;
280
forecastList["periods of rain or snow"] = RainSnow;
281
forecastList["periods of snow"] = Snow;
282
forecastList["periods of snow and blizzard"] = Snow;
283
forecastList["periods of snow and blizzard and blowing snow"] = Snow;
284
forecastList["periods of snow and blowing snow"] = Snow;
285
forecastList["periods of snow mixed with freezing drizzle"] = RainSnow;
286
forecastList["periods of snow mixed with freezing rain"] = RainSnow;
287
forecastList["periods of snow mixed with ice pellets"] = Snow;
288
forecastList["periods of snow mixed with rain"] = RainSnow;
289
forecastList["periods of snow or freezing drizzle"] = RainSnow;
290
forecastList["periods of snow or freezing rain"] = RainSnow;
291
forecastList["periods of snow or ice pellets"] = Snow;
292
forecastList["periods of snow or rain"] = RainSnow;
293
forecastList["periods of rain or snow"] = RainSnow;
294
forecastList["periods of wet snow"] = Snow;
295
forecastList["periods of wet snow mixed with rain"] = RainSnow;
296
forecastList["periods of wet snow or rain"] = RainSnow;
297
forecastList["rain"] = Rain;
298
forecastList["rain at times heavy"] = Rain;
299
forecastList["rain at times heavy mixed with freezing rain"] = FreezingRain;
300
forecastList["rain at times heavy mixed with snow"] = RainSnow;
301
forecastList["rain at times heavy or drizzle"] = Rain;
302
forecastList["rain at times heavy or freezing rain"] = Rain;
303
forecastList["rain at times heavy or snow"] = RainSnow;
304
forecastList["rain at times heavy or thundershowers"] = Showers;
305
forecastList["rain at times heavy or thunderstorms"] = Thunderstorm;
306
forecastList["rain mixed with freezing rain"] = FreezingRain;
307
forecastList["rain mixed with snow"] = RainSnow;
308
forecastList["rain or drizzle"] = Rain;
309
forecastList["rain or freezing rain"] = Rain;
310
forecastList["rain or snow"] = RainSnow;
311
forecastList["rain or thundershowers"] = Showers;
312
forecastList["rain or thunderstorms"] = Thunderstorm;
313
forecastList["rain showers or flurries"] = RainSnow;
314
forecastList["rain showers or wet flurries"] = RainSnow;
315
forecastList["showers"] = Showers;
316
forecastList["showers at times heavy"] = Showers;
317
forecastList["showers at times heavy or thundershowers"] = Showers;
318
forecastList["showers at times heavy or thunderstorms"] = Thunderstorm;
319
forecastList["showers or drizzle"] = Showers;
320
forecastList["showers or thundershowers"] = Thunderstorm;
321
forecastList["showers or thunderstorms"] = Thunderstorm;
322
forecastList["smoke"] = NotAvailable;
323
forecastList["snow"] = Snow;
324
forecastList["snow and blizzard"] = Snow;
325
forecastList["snow and blizzard and blowing snow"] = Snow;
326
forecastList["snow and blowing snow"] = Snow;
327
forecastList["snow at times heavy"] = Snow;
328
forecastList["snow at times heavy and blizzard"] = Snow;
329
forecastList["snow at times heavy and blowing snow"] = Snow;
330
forecastList["snow at times heavy mixed with freezing drizzle"] = RainSnow;
331
forecastList["snow at times heavy mixed with freezing rain"] = RainSnow;
332
forecastList["snow at times heavy mixed with ice pellets"] = Snow;
333
forecastList["snow at times heavy mixed with rain"] = RainSnow;
334
forecastList["snow at times heavy or freezing rain"] = RainSnow;
335
forecastList["snow at times heavy or ice pellets"] = Snow;
336
forecastList["snow at times heavy or rain"] = RainSnow;
337
forecastList["snow mixed with freezing drizzle"] = RainSnow;
338
forecastList["snow mixed with freezing rain"] = RainSnow;
339
forecastList["snow mixed with ice pellets"] = Snow;
340
forecastList["snow mixed with rain"] = RainSnow;
341
forecastList["snow or freezing drizzle"] = RainSnow;
342
forecastList["snow or freezing rain"] = RainSnow;
343
forecastList["snow or ice pellets"] = Snow;
344
forecastList["snow or rain"] = RainSnow;
345
forecastList["snow squalls"] = Snow;
346
forecastList["sunny"] = ClearDay;
347
forecastList["sunny with cloudy periods"] = PartlyCloudyDay;
348
forecastList["thunderstorms"] = Thunderstorm;
349
forecastList["thunderstorms and possible hail"] = Thunderstorm;
350
forecastList["wet flurries"] = Flurries;
351
forecastList["wet flurries at times heavy"] = Flurries;
352
forecastList["wet flurries at times heavy or rain snowers"] = RainSnow;
353
forecastList["wet flurries or rain showers"] = RainSnow;
354
forecastList["wet snow"] = Snow;
355
forecastList["wet snow at times heavy"] = Snow;
356
forecastList["wet snow at times heavy mixed with rain"] = RainSnow;
357
forecastList["wet snow mixed with rain"] = RainSnow;
358
forecastList["wet snow or rain"] = RainSnow;
359
forecastList["windy"] = NotAvailable;
361
forecastList["chance of drizzle mixed with freezing drizzle"] = LightRain;
362
forecastList["chance of flurries mixed with ice pellets"] = Flurries;
363
forecastList["chance of flurries or ice pellets"] = Flurries;
364
forecastList["chance of flurries or rain showers"] = RainSnow;
365
forecastList["chance of flurries or thundershowers"] = RainSnow;
366
forecastList["chance of freezing drizzle"] = FreezingDrizzle;
367
forecastList["chance of freezing rain"] = FreezingRain;
368
forecastList["chance of freezing rain mixed with snow"] = RainSnow;
369
forecastList["chance of freezing rain or rain"] = FreezingRain;
370
forecastList["chance of freezing rain or snow"] = RainSnow;
371
forecastList["chance of light snow and blowing snow"] = LightSnow;
372
forecastList["chance of light snow mixed with freezing drizzle"] = LightSnow;
373
forecastList["chance of light snow mixed with ice pellets"] = LightSnow;
374
forecastList["chance of light snow mixed with rain"] = RainSnow;
375
forecastList["chance of light snow or freezing rain"] = RainSnow;
376
forecastList["chance of light snow or ice pellets"] = LightSnow;
377
forecastList["chance of light snow or rain"] = RainSnow;
378
forecastList["chance of light wet snow"] = Snow;
379
forecastList["chance of rain"] = Rain;
380
forecastList["chance of rain at times heavy"] = Rain;
381
forecastList["chance of rain mixed with snow"] = RainSnow;
382
forecastList["chance of rain or drizzle"] = Rain;
383
forecastList["chance of rain or freezing rain"] = Rain;
384
forecastList["chance of rain or snow"] = RainSnow;
385
forecastList["chance of rain showers or flurries"] = RainSnow;
386
forecastList["chance of rain showers or wet flurries"] = RainSnow;
387
forecastList["chance of severe thunderstorms"] = Thunderstorm;
388
forecastList["chance of showers at times heavy"] = Rain;
389
forecastList["chance of showers at times heavy or thundershowers"] = Thunderstorm;
390
forecastList["chance of showers at times heavy or thunderstorms"] = Thunderstorm;
391
forecastList["chance of showers or thundershowers"] = Thunderstorm;
392
forecastList["chance of showers or thunderstorms"] = Thunderstorm;
393
forecastList["chance of snow"] = Snow;
394
forecastList["chance of snow and blizzard"] = Snow;
395
forecastList["chance of snow mixed with freezing drizzle"] = Snow;
396
forecastList["chance of snow mixed with freezing rain"] = RainSnow;
397
forecastList["chance of snow mixed with rain"] = RainSnow;
398
forecastList["chance of snow or rain"] = RainSnow;
399
forecastList["chance of snow squalls"] = Snow;
400
forecastList["chance of thundershowers"] = Showers;
401
forecastList["chance of thunderstorms"] = Thunderstorm;
402
forecastList["chance of thunderstorms and possible hail"] = Thunderstorm;
403
forecastList["chance of wet flurries"] = Flurries;
404
forecastList["chance of wet flurries at times heavy"] = Flurries;
405
forecastList["chance of wet flurries or rain showers"] = RainSnow;
406
forecastList["chance of wet snow"] = Snow;
407
forecastList["chance of wet snow mixed with rain"] = RainSnow;
408
forecastList["chance of wet snow or rain"] = RainSnow;
413
QMap<QString, IonInterface::ConditionIcons> const& EnvCanadaIon::conditionIcons(void) const
415
static QMap<QString, ConditionIcons> const condval = setupConditionIconMappings();
419
QMap<QString, IonInterface::ConditionIcons> const& EnvCanadaIon::forecastIcons(void) const
421
static QMap<QString, ConditionIcons> const foreval = setupForecastIconMappings();
425
QStringList EnvCanadaIon::validate(const QString& source) const
427
QStringList placeList;
428
QString sourceNormalized = source.toUpper();
429
QHash<QString, EnvCanadaIon::XMLMapInfo>::const_iterator it = m_places.constBegin();
430
while (it != m_places.constEnd()) {
431
if (it.key().toUpper().contains(sourceNormalized)) {
432
placeList.append(QString("place|").append(it.key()));
437
// Check if placeList is empty if so, return nothing.
438
if (placeList.isEmpty()) {
439
return QStringList();
445
// Get a specific Ion's data
446
bool EnvCanadaIon::updateIonSource(const QString& source)
448
//kDebug() << "updateIonSource()" << source;
450
// We expect the applet to send the source in the following tokenization:
451
// ionname|validate|place_name - Triggers validation of place
452
// ionname|weather|place_name - Triggers receiving weather of place
454
QStringList sourceAction = source.split('|');
456
// Guard: if the size of array is not 2 then we have bad data, return an error
457
if (sourceAction.size() < 2) {
458
setData(source, "validate", "envcan|malformed");
462
if (sourceAction[1] == "validate" && sourceAction.size() > 2) {
463
QStringList result = validate(sourceAction[2]);
465
if (result.size() == 1) {
466
setData(source, "validate", QString("envcan|valid|single|").append(result.join("|")));
468
} else if (result.size() > 1) {
469
setData(source, "validate", QString("envcan|valid|multiple|").append(result.join("|")));
471
} else if (result.size() == 0) {
472
setData(source, "validate", QString("envcan|invalid|single|").append(sourceAction[2]));
476
} else if (sourceAction[1] == "weather" && sourceAction.size() > 2) {
480
setData(source, "validate", "envcan|malformed");
486
// Parses city list and gets the correct city based on ID number
487
void EnvCanadaIon::getXMLSetup()
489
//kDebug() << "getXMLSetup()";
491
// If network is down, we need to spin and wait
493
KIO::TransferJob *job = KIO::get(KUrl("http://dd.weatheroffice.ec.gc.ca/citypage_weather/xml/siteList.xml"), KIO::NoReload, KIO::HideProgressInfo);
496
connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
497
SLOT(setup_slotDataArrived(KIO::Job *, const QByteArray &)));
498
connect(job, SIGNAL(result(KJob *)), this, SLOT(setup_slotJobFinished(KJob *)));
501
// Gets specific city XML data
502
void EnvCanadaIon::getXMLData(const QString& source)
504
foreach (const QString &fetching, m_jobList) {
505
if (fetching == source) {
506
// already getting this source and awaiting the data
511
//kDebug() << source;
513
// Demunge source name for key only.
514
QString dataKey = source;
515
dataKey.remove("envcan|weather|");
517
KUrl url = QString("http://dd.weatheroffice.ec.gc.ca/citypage_weather/xml/" + m_places[dataKey].territoryName + "/" + m_places[dataKey].cityCode + "_e.xml");
518
//url="file:///home/spstarr/Desktop/s0000649_e.xml";
519
//kDebug() << "Will Try URL: " << url;
521
if (m_places[dataKey].territoryName.isEmpty() && m_places[dataKey].cityCode.isEmpty()) {
522
setData(source, "validate", QString("envcan|malformed"));
526
KIO::TransferJob* const newJob = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
528
m_jobXml.insert(newJob, new QXmlStreamReader);
529
m_jobList.insert(newJob, source);
531
connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)), this,
532
SLOT(slotDataArrived(KIO::Job *, const QByteArray &)));
533
connect(newJob, SIGNAL(result(KJob *)), this, SLOT(slotJobFinished(KJob *)));
536
void EnvCanadaIon::setup_slotDataArrived(KIO::Job *job, const QByteArray &data)
540
if (data.isEmpty()) {
541
//kDebug() << "done!";
547
m_xmlSetup.addData(data);
550
void EnvCanadaIon::slotDataArrived(KIO::Job *job, const QByteArray &data)
553
if (data.isEmpty() || !m_jobXml.contains(job)) {
558
m_jobXml[job]->addData(data);
561
void EnvCanadaIon::slotJobFinished(KJob *job)
563
// Dual use method, if we're fetching location data to parse we need to do this first
564
const QString source = m_jobList.value(job);
565
//kDebug() << source << m_sourcesToReset.contains(source);
566
setData(source, Data());
567
QXmlStreamReader *reader = m_jobXml.value(job);
569
readXMLData(m_jobList[job], *reader);
572
m_jobList.remove(job);
573
delete m_jobXml[job];
574
m_jobXml.remove(job);
576
if (m_sourcesToReset.contains(source)) {
577
m_sourcesToReset.removeAll(source);
579
// so the weather engine updates it's data
580
forceImmediateUpdateOfAllVisualizations();
582
// update the clients of our engine
583
emit forceUpdate(this, source);
587
void EnvCanadaIon::setup_slotJobFinished(KJob *job)
590
const bool success = readXMLSetup();
592
//kDebug() << success << m_sourcesToReset;
593
setInitialized(success);
596
// Parse the city list and store into a QMap
597
bool EnvCanadaIon::readXMLSetup()
599
bool success = false;
604
//kDebug() << "readXMLSetup()";
606
while (!m_xmlSetup.atEnd()) {
607
m_xmlSetup.readNext();
609
if (m_xmlSetup.isStartElement()) {
611
// XML ID code to match filename
612
if (m_xmlSetup.name() == "site") {
613
code = m_xmlSetup.attributes().value("code").toString();
616
if (m_xmlSetup.name() == "nameEn") {
617
cityName = m_xmlSetup.readElementText(); // Name of cities
620
if (m_xmlSetup.name() == "provinceCode") {
621
territory = m_xmlSetup.readElementText(); // Provinces/Territory list
625
if (m_xmlSetup.isEndElement() && m_xmlSetup.name() == "site") {
626
EnvCanadaIon::XMLMapInfo info;
627
QString tmp = cityName + ", " + territory; // Build the key name.
630
info.cityCode = code;
631
info.territoryName = territory;
632
info.cityName = cityName;
634
// Set the string list, we will use for the applet to display the available cities.
635
m_places[tmp] = info;
641
return (success && !m_xmlSetup.error());
644
void EnvCanadaIon::parseWeatherSite(WeatherData& data, QXmlStreamReader& xml)
646
while (!xml.atEnd()) {
649
if (xml.isStartElement()) {
650
if (xml.name() == "license") {
651
xml.readElementText();
652
} else if (xml.name() == "location") {
653
parseLocations(data, xml);
654
} else if (xml.name() == "warnings") {
655
// Cleanup warning list on update
656
data.warnings.clear();
657
data.watches.clear();
658
parseWarnings(data, xml);
659
} else if (xml.name() == "currentConditions") {
660
parseConditions(data, xml);
661
} else if (xml.name() == "forecastGroup") {
662
// Clean up forecast list on update
663
data.forecasts.clear();
664
parseWeatherForecast(data, xml);
665
} else if (xml.name() == "yesterdayConditions") {
666
parseYesterdayWeather(data, xml);
667
} else if (xml.name() == "riseSet") {
668
parseAstronomicals(data, xml);
669
} else if (xml.name() == "almanac") {
670
parseWeatherRecords(data, xml);
672
parseUnknownElement(xml);
678
// Parse Weather data main loop, from here we have to decend into each tag pair
679
bool EnvCanadaIon::readXMLData(const QString& source, QXmlStreamReader& xml)
682
data.comforttemp = i18n("N/A");
683
data.recordHigh = 0.0;
684
data.recordLow = 0.0;
686
//kDebug() << "readXMLData()";
688
QString dataKey = source;
689
dataKey.remove("envcan|weather|");
690
data.shortTerritoryName = m_places[dataKey].territoryName;
691
while (!xml.atEnd()) {
694
if (xml.isEndElement()) {
698
if (xml.isStartElement()) {
699
if (xml.name() == "siteData") {
700
parseWeatherSite(data, xml);
702
parseUnknownElement(xml);
707
m_weatherData[source] = data;
708
updateWeather(source);
712
void EnvCanadaIon::parseDateTime(WeatherData& data, QXmlStreamReader& xml, WeatherData::WeatherEvent *event)
715
Q_ASSERT(xml.isStartElement() && xml.name() == "dateTime");
717
// What kind of date info is this?
718
QString dateType = xml.attributes().value("name").toString();
719
QString dateZone = xml.attributes().value("zone").toString();
721
QString selectTimeStamp;
723
while (!xml.atEnd()) {
726
if (xml.isEndElement()) {
730
if (xml.isStartElement()) {
731
if (dateType == "xmlCreation") {
734
if (dateZone == "UTC") {
737
if (xml.name() == "year") {
738
xml.readElementText();
739
} else if (xml.name() == "month") {
740
xml.readElementText();
741
} else if (xml.name() == "day") {
742
xml.readElementText();
743
} else if (xml.name() == "hour")
744
xml.readElementText();
745
else if (xml.name() == "minute")
746
xml.readElementText();
747
else if (xml.name() == "timeStamp")
748
selectTimeStamp = xml.readElementText();
749
else if (xml.name() == "textSummary") {
750
if (dateType == "eventIssue") {
752
event->timestamp = xml.readElementText();
754
} else if (dateType == "observation") {
755
xml.readElementText();
756
m_dateFormat = QDateTime::fromString(selectTimeStamp, "yyyyMMddHHmmss");
757
data.obsTimestamp = m_dateFormat.toString("dd.MM.yyyy @ hh:mm");
758
data.iconPeriodHour = m_dateFormat.toString("hh").toInt();
759
data.iconPeriodMinute = m_dateFormat.toString("mm").toInt();
760
} else if (dateType == "forecastIssue") {
761
data.forecastTimestamp = xml.readElementText();
762
} else if (dateType == "sunrise") {
763
data.sunriseTimestamp = xml.readElementText();
764
} else if (dateType == "sunset") {
765
data.sunsetTimestamp = xml.readElementText();
766
} else if (dateType == "moonrise") {
767
data.moonriseTimestamp = xml.readElementText();
768
} else if (dateType == "moonset") {
769
data.moonsetTimestamp = xml.readElementText();
776
void EnvCanadaIon::parseLocations(WeatherData& data, QXmlStreamReader& xml)
778
Q_ASSERT(xml.isStartElement() && xml.name() == "location");
780
while (!xml.atEnd()) {
783
if (xml.isEndElement()) {
787
if (xml.isStartElement()) {
788
if (xml.name() == "country") {
789
data.countryName = xml.readElementText();
790
} else if (xml.name() == "province" || xml.name() == "territory") {
791
data.longTerritoryName = xml.readElementText();
792
} else if (xml.name() == "name") {
793
data.cityName = xml.readElementText();
794
} else if (xml.name() == "region") {
795
data.regionName = xml.readElementText();
797
parseUnknownElement(xml);
803
void EnvCanadaIon::parseWindInfo(WeatherData& data, QXmlStreamReader& xml)
805
Q_ASSERT(xml.isStartElement() && xml.name() == "wind");
807
while (!xml.atEnd()) {
810
if (xml.isEndElement()) {
814
if (xml.isStartElement()) {
815
if (xml.name() == "speed") {
816
data.windSpeed = xml.readElementText();
817
} else if (xml.name() == "gust") {
818
data.windGust = xml.readElementText();
819
} else if (xml.name() == "direction") {
820
data.windDirection = xml.readElementText();
821
} else if (xml.name() == "bearing") {
822
data.windDegrees = xml.attributes().value("degrees").toString();
824
parseUnknownElement(xml);
830
void EnvCanadaIon::parseConditions(WeatherData& data, QXmlStreamReader& xml)
833
Q_ASSERT(xml.isStartElement() && xml.name() == "currentConditions");
834
data.temperature = i18n("N/A");
835
data.dewpoint = i18n("N/A");
836
data.condition = i18n("N/A");
837
data.comforttemp = i18n("N/A");
838
data.stationID = i18n("N/A");
839
data.stationLat = i18n("N/A");
840
data.stationLon = i18n("N/A");
842
data.pressureTendency = i18n("N/A");
844
data.humidity = i18n("N/A");
845
data.windSpeed = i18n("N/A");
846
data.windGust = i18n("N/A");
848
while (!xml.atEnd()) {
851
if (xml.isEndElement() && xml.name() == "currentConditions")
854
if (xml.isStartElement()) {
855
if (xml.name() == "station") {
856
data.stationID = xml.attributes().value("code").toString();
857
data.stationLat = xml.attributes().value("lat").toString();
858
data.stationLon = xml.attributes().value("lon").toString();
859
} else if (xml.name() == "dateTime") {
860
parseDateTime(data, xml);
861
} else if (xml.name() == "condition") {
862
data.condition = xml.readElementText();
863
} else if (xml.name() == "temperature") {
864
data.temperature = xml.readElementText();
865
} else if (xml.name() == "dewpoint") {
866
data.dewpoint = xml.readElementText();
867
} else if (xml.name() == "humidex" || xml.name() == "windChill") {
868
data.comforttemp = xml.readElementText();
869
} else if (xml.name() == "pressure") {
870
data.pressureTendency = xml.attributes().value("tendency").toString();
871
if (data.pressureTendency.isEmpty()) {
872
data.pressureTendency = "steady";
874
data.pressure = xml.readElementText().toFloat();
875
} else if (xml.name() == "visibility") {
876
data.visibility = xml.readElementText().toFloat();
877
} else if (xml.name() == "relativeHumidity") {
878
data.humidity = xml.readElementText();
879
} else if (xml.name() == "wind") {
880
parseWindInfo(data, xml);
883
// parseUnknownElement(xml);
887
if (data.temperature.isEmpty()) {
888
data.temperature = i18n("N/A");
892
void EnvCanadaIon::parseWarnings(WeatherData &data, QXmlStreamReader& xml)
894
WeatherData::WeatherEvent *watch = new WeatherData::WeatherEvent;
895
WeatherData::WeatherEvent *warning = new WeatherData::WeatherEvent;
897
Q_ASSERT(xml.isStartElement() && xml.name() == "warnings");
898
QString eventURL = xml.attributes().value("url").toString();
901
while (!xml.atEnd()) {
904
if (xml.isEndElement() && xml.name() == "warnings") {
908
if (xml.isStartElement()) {
909
if (xml.name() == "dateTime") {
911
parseDateTime(data, xml, watch);
914
parseDateTime(data, xml, warning);
917
if (!warning->timestamp.isEmpty() && !warning->url.isEmpty()) {
918
data.warnings.append(warning);
919
warning = new WeatherData::WeatherEvent;
921
if (!watch->timestamp.isEmpty() && !watch->url.isEmpty()) {
922
data.watches.append(watch);
923
watch = new WeatherData::WeatherEvent;
926
} else if (xml.name() == "event") {
927
// Append new event to list.
928
QString eventType = xml.attributes().value("type").toString();
929
if (eventType == "watch") {
930
watch->url = eventURL;
931
watch->type = eventType;
932
watch->priority = xml.attributes().value("priority").toString();
933
watch->description = xml.attributes().value("description").toString();
937
if (eventType == "warning") {
938
warning->url = eventURL;
939
warning->type = eventType;
940
warning->priority = xml.attributes().value("priority").toString();
941
warning->description = xml.attributes().value("description").toString();
945
if (xml.name() != "dateTime") {
946
parseUnknownElement(xml);
956
void EnvCanadaIon::parseWeatherForecast(WeatherData& data, QXmlStreamReader& xml)
958
WeatherData::ForecastInfo* forecast = new WeatherData::ForecastInfo;
959
Q_ASSERT(xml.isStartElement() && xml.name() == "forecastGroup");
961
while (!xml.atEnd()) {
964
if (xml.isEndElement() && xml.name() == "forecastGroup") {
968
if (xml.isStartElement()) {
969
if (xml.name() == "dateTime") {
970
parseDateTime(data, xml);
971
} else if (xml.name() == "regionalNormals") {
972
parseRegionalNormals(data, xml);
973
} else if (xml.name() == "forecast") {
974
parseForecast(data, xml, forecast);
975
forecast = new WeatherData::ForecastInfo;
977
parseUnknownElement(xml);
984
void EnvCanadaIon::parseRegionalNormals(WeatherData& data, QXmlStreamReader& xml)
986
Q_ASSERT(xml.isStartElement() && xml.name() == "regionalNormals");
988
while (!xml.atEnd()) {
991
if (xml.isEndElement()) {
995
if (xml.isStartElement()) {
996
if (xml.name() == "textSummary") {
997
xml.readElementText();
998
} else if (xml.name() == "temperature" && xml.attributes().value("class") == "high") {
999
data.normalHigh = xml.readElementText();
1000
} else if (xml.name() == "temperature" && xml.attributes().value("class") == "low") {
1001
data.normalLow = xml.readElementText();
1007
void EnvCanadaIon::parseForecast(WeatherData& data, QXmlStreamReader& xml, WeatherData::ForecastInfo *forecast)
1010
Q_ASSERT(xml.isStartElement() && xml.name() == "forecast");
1012
while (!xml.atEnd()) {
1015
if (xml.isEndElement() && xml.name() == "forecast") {
1016
data.forecasts.append(forecast);
1020
if (xml.isStartElement()) {
1021
if (xml.name() == "period") {
1022
forecast->forecastPeriod = xml.attributes().value("textForecastName").toString();
1023
} else if (xml.name() == "textSummary") {
1024
forecast->forecastSummary = xml.readElementText();
1025
} else if (xml.name() == "abbreviatedForecast") {
1026
parseShortForecast(forecast, xml);
1027
} else if (xml.name() == "temperatures") {
1028
parseForecastTemperatures(forecast, xml);
1029
} else if (xml.name() == "winds") {
1030
parseWindForecast(forecast, xml);
1031
} else if (xml.name() == "precipitation") {
1032
parsePrecipitationForecast(forecast, xml);
1033
} else if (xml.name() == "uv") {
1034
data.UVRating = xml.attributes().value("category").toString();
1035
parseUVIndex(data, xml);
1036
// else if (xml.name() == "frost") { FIXME: Wait until winter to see what this looks like.
1037
// parseFrost(xml, forecast);
1039
if (xml.name() != "forecast") {
1040
parseUnknownElement(xml);
1047
void EnvCanadaIon::parseShortForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1049
Q_ASSERT(xml.isStartElement() && xml.name() == "abbreviatedForecast");
1053
while (!xml.atEnd()) {
1056
if (xml.isEndElement() && xml.name() == "abbreviatedForecast") {
1060
if (xml.isStartElement()) {
1061
if (xml.name() == "pop") {
1062
forecast->popPrecent = xml.readElementText();
1064
if (xml.name() == "textSummary") {
1065
shortText = xml.readElementText();
1066
QMap<QString, ConditionIcons> forecastList;
1067
forecastList = forecastIcons();
1068
if ((forecast->forecastPeriod == "tonight") || (forecast->forecastPeriod.contains("night"))) {
1069
forecastList["a few clouds"] = FewCloudsNight;
1070
forecastList["cloudy periods"] = PartlyCloudyNight;
1071
forecastList["chance of drizzle mixed with rain"] = ChanceShowersNight;
1072
forecastList["chance of drizzle"] = ChanceShowersNight;
1073
forecastList["chance of drizzle or rain"] = ChanceShowersNight;
1074
forecastList["chance of flurries"] = ChanceSnowNight;
1075
forecastList["chance of light snow"] = ChanceSnowNight;
1076
forecastList["chance of flurries at times heavy"] = ChanceSnowNight;
1077
forecastList["chance of showers or drizzle"] = ChanceShowersNight;
1078
forecastList["chance of showers"] = ChanceShowersNight;
1079
forecastList["clearing"] = ClearNight;
1081
forecastList["a few clouds"] = FewCloudsDay;
1082
forecastList["cloudy periods"] = PartlyCloudyDay;
1083
forecastList["chance of drizzle mixed with rain"] = ChanceShowersDay;
1084
forecastList["chance of drizzle"] = ChanceShowersDay;
1085
forecastList["chance of drizzle or rain"] = ChanceShowersDay;
1086
forecastList["chance of flurries"] = ChanceSnowDay;
1087
forecastList["chance of light snow"] = ChanceSnowDay;
1088
forecastList["chance of flurries at times heavy"] = ChanceSnowDay;
1089
forecastList["chance of showers or drizzle"] = ChanceShowersDay;
1090
forecastList["chance of showers"] = ChanceShowersDay;
1091
forecastList["clearing"] = ClearDay;
1093
forecast->shortForecast = shortText;
1094
forecast->iconName = getWeatherIcon(forecastList, shortText.toLower());
1100
void EnvCanadaIon::parseUVIndex(WeatherData& data, QXmlStreamReader& xml)
1102
Q_ASSERT(xml.isStartElement() && xml.name() == "uv");
1104
while (!xml.atEnd()) {
1107
if (xml.isEndElement() && xml.name() == "uv") {
1111
if (xml.isStartElement()) {
1112
if (xml.name() == "index") {
1113
data.UVIndex = xml.readElementText();
1115
if (xml.name() == "textSummary") {
1116
xml.readElementText();
1122
void EnvCanadaIon::parseForecastTemperatures(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1124
Q_ASSERT(xml.isStartElement() && xml.name() == "temperatures");
1126
while (!xml.atEnd()) {
1129
if (xml.isEndElement() && xml.name() == "temperatures") {
1133
if (xml.isStartElement()) {
1134
if (xml.name() == "temperature" && xml.attributes().value("class") == "low") {
1135
forecast->forecastTempLow = xml.readElementText();
1136
} else if (xml.name() == "temperature" && xml.attributes().value("class") == "high") {
1137
forecast->forecastTempHigh = xml.readElementText();
1138
} else if (xml.name() == "textSummary") {
1139
xml.readElementText();
1145
void EnvCanadaIon::parsePrecipitationForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1147
Q_ASSERT(xml.isStartElement() && xml.name() == "precipitation");
1149
while (!xml.atEnd()) {
1152
if (xml.isEndElement() && xml.name() == "precipitation") {
1156
if (xml.isStartElement()) {
1157
if (xml.name() == "textSummary") {
1158
forecast->precipForecast = xml.readElementText();
1159
} else if (xml.name() == "precipType") {
1160
forecast->precipType = xml.readElementText();
1161
} else if (xml.name() == "accumulation") {
1162
parsePrecipTotals(forecast, xml);
1168
void EnvCanadaIon::parsePrecipTotals(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1170
Q_ASSERT(xml.isStartElement() && xml.name() == "accumulation");
1172
while (!xml.atEnd()) {
1175
if (xml.isEndElement() && xml.name() == "accumulation") {
1179
if (xml.name() == "name") {
1180
xml.readElementText();
1181
} else if (xml.name() == "amount") {
1182
forecast->precipTotalExpected = xml.readElementText();
1187
void EnvCanadaIon::parseWindForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader& xml)
1189
Q_ASSERT(xml.isStartElement() && xml.name() == "winds");
1191
while (!xml.atEnd()) {
1194
if (xml.isEndElement() && xml.name() == "winds") {
1198
if (xml.isStartElement()) {
1199
if (xml.name() == "textSummary") {
1200
forecast->windForecast = xml.readElementText();
1202
if (xml.name() != "winds") {
1203
parseUnknownElement(xml);
1210
void EnvCanadaIon::parseYesterdayWeather(WeatherData& data, QXmlStreamReader& xml)
1212
Q_ASSERT(xml.isStartElement() && xml.name() == "yesterdayConditions");
1214
while (!xml.atEnd()) {
1217
if (xml.isEndElement()) {
1221
if (xml.isStartElement()) {
1222
if (xml.name() == "temperature" && xml.attributes().value("class") == "high") {
1223
data.prevHigh = xml.readElementText();
1224
} else if (xml.name() == "temperature" && xml.attributes().value("class") == "low") {
1225
data.prevLow = xml.readElementText();
1226
} else if (xml.name() == "precip") {
1227
data.prevPrecipType = xml.attributes().value("units").toString();
1228
if (data.prevPrecipType.isEmpty()) {
1229
data.prevPrecipType = QString::number(KUnitConversion::NoUnit);
1231
data.prevPrecipTotal = xml.readElementText();
1237
void EnvCanadaIon::parseWeatherRecords(WeatherData& data, QXmlStreamReader& xml)
1239
Q_ASSERT(xml.isStartElement() && xml.name() == "almanac");
1241
while (!xml.atEnd()) {
1244
if (xml.isEndElement() && xml.name() == "almanac") {
1248
if (xml.isStartElement()) {
1249
if (xml.name() == "temperature" && xml.attributes().value("class") == "extremeMax") {
1250
data.recordHigh = xml.readElementText().toFloat();
1251
} else if (xml.name() == "temperature" && xml.attributes().value("class") == "extremeMin") {
1252
data.recordLow = xml.readElementText().toFloat();
1253
} else if (xml.name() == "precipitation" && xml.attributes().value("class") == "extremeRainfall") {
1254
data.recordRain = xml.readElementText().toFloat();
1255
} else if (xml.name() == "precipitation" && xml.attributes().value("class") == "extremeSnowfall") {
1256
data.recordSnow = xml.readElementText().toFloat();
1262
void EnvCanadaIon::parseAstronomicals(WeatherData& data, QXmlStreamReader& xml)
1264
Q_ASSERT(xml.isStartElement() && xml.name() == "riseSet");
1266
while (!xml.atEnd()) {
1269
if (xml.isEndElement() && xml.name() == "riseSet") {
1273
if (xml.isStartElement()) {
1274
if (xml.name() == "disclaimer") {
1275
xml.readElementText();
1276
} else if (xml.name() == "dateTime") {
1277
parseDateTime(data, xml);
1283
// handle when no XML tag is found
1284
void EnvCanadaIon::parseUnknownElement(QXmlStreamReader& xml) const
1287
while (!xml.atEnd()) {
1290
if (xml.isEndElement()) {
1294
if (xml.isStartElement()) {
1295
parseUnknownElement(xml);
1300
void EnvCanadaIon::updateWeather(const QString& source)
1302
//kDebug() << "updateWeather()";
1304
QMap<QString, QString> dataFields;
1305
Plasma::DataEngine::Data data;
1306
QStringList fieldList;
1307
QVector<QString> forecastList;
1310
data.insert("Country", country(source));
1311
data.insert("Place", QString("%1, %2").arg(city(source)).arg(territory(source)));
1312
data.insert("Region", region(source));
1313
data.insert("Station", station(source));
1315
data.insert("Latitude", latitude(source));
1316
data.insert("Longitude", longitude(source));
1318
// Real weather - Current conditions
1319
data.insert("Observation Period", observationTime(source));
1320
data.insert("Current Conditions", i18nc("weather condition", condition(source).toUtf8()));
1321
//kDebug() << "i18n condition string: " << qPrintable(condition(source));
1323
// Tell applet which icon to use for conditions and provide mapping for condition type to the icons to display
1324
QMap<QString, ConditionIcons> conditionList;
1325
conditionList = conditionIcons();
1327
const double lati = latitude(source).replace(QRegExp("[^0-9.]"), NULL).toDouble();
1328
const double longi = longitude(source).replace(QRegExp("[^0-9.]"), NULL).toDouble();
1329
const Plasma::DataEngine::Data timeData = m_timeEngine->query(
1330
QString("Local|Solar|Latitude=%1|Longitude=%2")
1331
.arg(lati).arg(-1 * longi));
1333
if (timeData["Corrected Elevation"].toDouble() < 0.0) {
1334
conditionList["decreasing cloud"] = FewCloudsNight;
1335
conditionList["mostly cloudy"] = PartlyCloudyNight;
1336
conditionList["partly cloudy"] = PartlyCloudyNight;
1337
conditionList["fair"] = FewCloudsNight;
1338
//kDebug() << "Before sunrise/After sunset - using night icons\n";
1340
conditionList["decreasing cloud"] = FewCloudsDay;
1341
conditionList["mostly cloudy"] = PartlyCloudyDay;
1342
conditionList["partly cloudy"] = PartlyCloudyDay;
1343
conditionList["fair"] = FewCloudsDay;
1344
//kDebug() << "Using daytime icons\n";
1347
data.insert("Condition Icon", getWeatherIcon(conditionList, condition(source)));
1349
dataFields = temperature(source);
1350
data.insert("Temperature", dataFields["temperature"]);
1352
// Do we have a comfort temperature? if so display it
1353
if (dataFields["comfortTemperature"] != "N/A" && !dataFields["comfortTemperature"].isEmpty()) {
1354
if (dataFields["comfortTemperature"].toFloat() <= 0) {
1355
data.insert("Windchill", QString("%1").arg(dataFields["comfortTemperature"]));
1356
data.insert("Humidex", i18n("N/A"));
1358
data.insert("Humidex", QString("%1").arg(dataFields["comfortTemperature"]));
1359
data.insert("Windchill", i18n("N/A"));
1362
data.insert("Windchill", i18n("N/A"));
1363
data.insert("Humidex", i18n("N/A"));
1366
// Used for all temperatures
1367
data.insert("Temperature Unit", dataFields["temperatureUnit"]);
1369
data.insert("Dewpoint", dewpoint(source));
1371
dataFields = pressure(source);
1372
data.insert("Pressure", dataFields["pressure"]);
1373
data.insert("Pressure Unit", dataFields["pressureUnit"]);
1374
data.insert("Pressure Tendency", dataFields["pressureTendency"]);
1376
dataFields = visibility(source);
1377
data.insert("Visibility", dataFields["visibility"]);
1378
data.insert("Visibility Unit", dataFields["visibilityUnit"]);
1380
dataFields = humidity(source);
1381
data.insert("Humidity", dataFields["humidity"]);
1382
data.insert("Humidity Unit", dataFields["humidityUnit"]);
1384
dataFields = wind(source);
1385
data.insert("Wind Speed", dataFields["windSpeed"]);
1386
data.insert("Wind Speed Unit", dataFields["windUnit"]);
1388
data.insert("Wind Gust", dataFields["windGust"]);
1389
data.insert("Wind Direction", dataFields["windDirection"]);
1390
data.insert("Wind Degrees", dataFields["windDegrees"]);
1391
data.insert("Wind Gust Unit", dataFields["windGustUnit"]);
1393
dataFields = regionalTemperatures(source);
1394
data.insert("Normal High", dataFields["normalHigh"]);
1395
data.insert("Normal Low", dataFields["normalLow"]);
1397
// Check if UV index is available for the location
1398
dataFields = uvIndex(source);
1399
data.insert("UV Index", dataFields["uvIndex"]);
1400
data.insert("UV Rating", dataFields["uvRating"]);
1402
dataFields = watches(source);
1404
// Set number of forecasts per day/night supported
1405
data.insert("Total Watches Issued", m_weatherData[source].watches.size());
1407
// Check if we have warnings or watches
1408
for (int i = 0; i < m_weatherData[source].watches.size(); i++) {
1409
fieldList = dataFields[QString("watch %1").arg(i)].split('|');
1410
data.insert(QString("Watch Priority %1").arg(i), fieldList[0]);
1411
data.insert(QString("Watch Description %1").arg(i), fieldList[1]);
1412
data.insert(QString("Watch Info %1").arg(i), fieldList[2]);
1413
data.insert(QString("Watch Timestamp %1").arg(i), fieldList[3]);
1416
dataFields = warnings(source);
1418
data.insert("Total Warnings Issued", m_weatherData[source].warnings.size());
1420
for (int k = 0; k < m_weatherData[source].warnings.size(); k++) {
1421
fieldList = dataFields[QString("warning %1").arg(k)].split('|');
1422
data.insert(QString("Warning Priority %1").arg(k), fieldList[0]);
1423
data.insert(QString("Warning Description %1").arg(k), fieldList[1]);
1424
data.insert(QString("Warning Info %1").arg(k), fieldList[2]);
1425
data.insert(QString("Warning Timestamp %1").arg(k), fieldList[3]);
1428
forecastList = forecasts(source);
1430
// Set number of forecasts per day/night supported
1431
data.insert("Total Weather Days", m_weatherData[source].forecasts.size());
1433
foreach(const QString &forecastItem, forecastList) {
1434
fieldList = forecastItem.split('|');
1436
data.insert(QString("Short Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6") \
1437
.arg(fieldList[0]).arg(fieldList[1]).arg(fieldList[2]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[5]));
1440
data.insert(QString("Long Forecast Day %1").arg(i), QString("%1|%2|%3|%4|%5|%6|%7|%8") \
1441
.arg(fieldList[0]).arg(fieldList[2]).arg(fieldList[3]).arg(fieldList[4]).arg(fieldList[6]) \
1442
.arg(fieldList[7]).arg(fieldList[8]).arg(fieldList[9]));
1447
dataFields = yesterdayWeather(source);
1448
data.insert("Yesterday High", dataFields["prevHigh"]);
1449
data.insert("Yesterday Low", dataFields["prevLow"]);
1451
data.insert("Yesterday Precip Total", dataFields["prevPrecip"]);
1452
data.insert("Yesterday Precip Unit", dataFields["prevPrecipUnit"]);
1454
dataFields = sunriseSet(source);
1455
data.insert("Sunrise At", dataFields["sunrise"]);
1456
data.insert("Sunset At", dataFields["sunset"]);
1458
dataFields = moonriseSet(source);
1459
data.insert("Moonrise At", dataFields["moonrise"]);
1460
data.insert("Moonset At", dataFields["moonset"]);
1462
dataFields = weatherRecords(source);
1463
data.insert("Record High Temperature", dataFields["recordHigh"]);
1464
data.insert("Record Low Temperature", dataFields["recordLow"]);
1466
data.insert("Record Rainfall", dataFields["recordRain"]);
1467
data.insert("Record Rainfall Unit", dataFields["recordRainUnit"]);
1468
data.insert("Record Snowfall", dataFields["recordSnow"]);
1469
data.insert("Record Snowfall Unit", dataFields["recordSnowUnit"]);
1471
data.insert("Credit", i18n("Meteorological data is provided by Environment Canada"));
1472
setData(source, data);
1475
QString const EnvCanadaIon::country(const QString& source) const
1477
// This will always return Canada
1478
return m_weatherData[source].countryName;
1481
QString EnvCanadaIon::territory(const QString& source) const
1483
return m_weatherData[source].shortTerritoryName;
1486
QString EnvCanadaIon::city(const QString& source) const
1488
return m_weatherData[source].cityName;
1491
QString EnvCanadaIon::region(const QString& source) const
1493
return m_weatherData[source].regionName;
1496
QString EnvCanadaIon::station(const QString& source) const
1498
if (!m_weatherData[source].stationID.isEmpty()) {
1499
return m_weatherData[source].stationID.toUpper();
1505
QString EnvCanadaIon::latitude(const QString& source) const
1507
return m_weatherData[source].stationLat;
1510
QString EnvCanadaIon::longitude(const QString& source) const
1512
return m_weatherData[source].stationLon;
1515
QString EnvCanadaIon::observationTime(const QString& source) const
1517
return m_weatherData[source].obsTimestamp;
1520
int EnvCanadaIon::periodHour(const QString& source) const
1522
return m_weatherData[source].iconPeriodHour;
1525
int EnvCanadaIon::periodMinute(const QString& source) const
1527
return m_weatherData[source].iconPeriodMinute;
1530
QString EnvCanadaIon::condition(const QString& source)
1532
if (m_weatherData[source].condition.isEmpty()) {
1533
m_weatherData[source].condition = i18n("N/A");
1535
return (m_weatherData[source].condition.toUtf8());
1538
QString EnvCanadaIon::dewpoint(const QString& source) const
1540
if (!m_weatherData[source].dewpoint.isEmpty()) {
1541
return (QString::number(m_weatherData[source].dewpoint.toFloat(), 'f', 1));
1546
QMap<QString, QString> EnvCanadaIon::humidity(const QString& source) const
1548
QMap<QString, QString> humidityInfo;
1549
if (!m_weatherData[source].humidity.isEmpty()) {
1550
humidityInfo.insert("humidity", m_weatherData[source].humidity);
1551
humidityInfo.insert("humidityUnit", QString::number(KUnitConversion::Percent));
1553
humidityInfo.insert("humidity", i18n("N/A"));
1554
humidityInfo.insert("humidityUnit", QString::number(KUnitConversion::NoUnit));
1556
return humidityInfo;
1559
QMap<QString, QString> EnvCanadaIon::visibility(const QString& source) const
1561
QMap<QString, QString> visibilityInfo;
1563
if (!m_weatherData[source].visibility == 0) {
1564
visibilityInfo.insert("visibility", QString::number(m_weatherData[source].visibility, 'f', 1));
1565
visibilityInfo.insert("visibilityUnit", QString::number(KUnitConversion::Kilometer));
1567
visibilityInfo.insert("visibility", i18n("N/A"));
1568
visibilityInfo.insert("visibilityUnit", QString::number(KUnitConversion::NoUnit));
1570
return visibilityInfo;
1573
QMap<QString, QString> EnvCanadaIon::temperature(const QString& source) const
1575
QMap<QString, QString> temperatureInfo;
1576
if (!m_weatherData[source].temperature.isEmpty()) {
1577
temperatureInfo.insert("temperature", QString::number(m_weatherData[source].temperature.toFloat(), 'f', 1));
1580
if (m_weatherData[source].temperature == i18n("N/A")) {
1581
temperatureInfo.insert("temperature", i18n("N/A"));
1584
temperatureInfo.insert("comfortTemperature", i18n("N/A"));
1586
if (m_weatherData[source].comforttemp != i18n("N/A")) {
1587
temperatureInfo.insert("comfortTemperature", m_weatherData[source].comforttemp);
1590
// This is used for not just current temperature but also 8 days. Cannot be NoUnit.
1591
temperatureInfo.insert("temperatureUnit", QString::number(KUnitConversion::Celsius));
1592
return temperatureInfo;
1595
QMap<QString, QString> EnvCanadaIon::watches(const QString& source) const
1597
QMap<QString, QString> watchData;
1599
for (int i = 0; i < m_weatherData[source].watches.size(); ++i) {
1600
watchType = QString("watch %1").arg(i);
1601
watchData[watchType] = QString("%1|%2|%3|%4").arg(m_weatherData[source].watches[i]->priority) \
1602
.arg(m_weatherData[source].watches[i]->description) \
1603
.arg(m_weatherData[source].watches[i]->url) \
1604
.arg(m_weatherData[source].watches[i]->timestamp);
1609
QMap<QString, QString> EnvCanadaIon::warnings(const QString& source) const
1611
QMap<QString, QString> warningData;
1613
for (int i = 0; i < m_weatherData[source].warnings.size(); ++i) {
1614
warnType = QString("warning %1").arg(i);
1615
warningData[warnType] = QString("%1|%2|%3|%4").arg(m_weatherData[source].warnings[i]->priority) \
1616
.arg(m_weatherData[source].warnings[i]->description) \
1617
.arg(m_weatherData[source].warnings[i]->url) \
1618
.arg(m_weatherData[source].warnings[i]->timestamp);
1623
QVector<QString> EnvCanadaIon::forecasts(const QString& source)
1625
QVector<QString> forecastData;
1627
// Do some checks for empty data
1628
for (int i = 0; i < m_weatherData[source].forecasts.size(); ++i) {
1629
if (m_weatherData[source].forecasts[i]->forecastPeriod.isEmpty()) {
1630
m_weatherData[source].forecasts[i]->forecastPeriod = i18n("N/A");
1632
if (m_weatherData[source].forecasts[i]->shortForecast.isEmpty()) {
1633
m_weatherData[source].forecasts[i]->shortForecast = i18n("N/A");
1635
if (m_weatherData[source].forecasts[i]->iconName.isEmpty()) {
1636
m_weatherData[source].forecasts[i]->iconName = i18n("N/A");
1638
if (m_weatherData[source].forecasts[i]->forecastSummary.isEmpty()) {
1639
m_weatherData[source].forecasts[i]->forecastSummary = i18n("N/A");
1641
if (m_weatherData[source].forecasts[i]->forecastTempHigh.isEmpty()) {
1642
m_weatherData[source].forecasts[i]->forecastTempHigh = i18n("N/A");
1644
if (m_weatherData[source].forecasts[i]->forecastTempLow.isEmpty()) {
1645
m_weatherData[source].forecasts[i]->forecastTempLow = i18n("N/A");
1647
if (m_weatherData[source].forecasts[i]->popPrecent.isEmpty()) {
1648
m_weatherData[source].forecasts[i]->popPrecent = i18n("N/A");
1650
if (m_weatherData[source].forecasts[i]->windForecast.isEmpty()) {
1651
m_weatherData[source].forecasts[i]->windForecast = i18n("N/A");
1653
if (m_weatherData[source].forecasts[i]->precipForecast.isEmpty()) {
1654
m_weatherData[source].forecasts[i]->precipForecast = i18n("N/A");
1656
if (m_weatherData[source].forecasts[i]->precipType.isEmpty()) {
1657
m_weatherData[source].forecasts[i]->precipType = i18n("N/A");
1659
if (m_weatherData[source].forecasts[i]->precipTotalExpected.isEmpty()) {
1660
m_weatherData[source].forecasts[i]->precipTotalExpected = i18n("N/A");
1664
for (int i = 0; i < m_weatherData[source].forecasts.size(); ++i) {
1665
// We need to shortform the day/night strings.
1667
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Today")) {
1668
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Today", i18n("day"));
1671
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Tonight")) {
1672
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Tonight", i18nc("Short for tonight", "nite"));
1675
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("night")) {
1676
m_weatherData[source].forecasts[i]->forecastPeriod.replace("night", i18nc("Short for night, appended to the end of the weekday", "nt"));
1679
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Saturday")) {
1680
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Saturday", i18nc("Short for Saturday", "Sat"));
1683
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Sunday")) {
1684
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Sunday", i18nc("Short for Sunday", "Sun"));
1687
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Monday")) {
1688
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Monday", i18nc("Short for Monday", "Mon"));
1691
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Tuesday")) {
1692
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Tuesday", i18nc("Short for Tuesday", "Tue"));
1695
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Wednesday")) {
1696
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Wednesday", i18nc("Short for Wednesday", "Wed"));
1699
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Thursday")) {
1700
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Thursday", i18nc("Short for Thursday", "Thu"));
1702
if (m_weatherData[source].forecasts[i]->forecastPeriod.contains("Friday")) {
1703
m_weatherData[source].forecasts[i]->forecastPeriod.replace("Friday", i18nc("Short for Friday", "Fri"));
1706
forecastData.append(QString("%1|%2|%3|%4|%5|%6") \
1707
.arg(m_weatherData[source].forecasts[i]->forecastPeriod) \
1708
.arg(m_weatherData[source].forecasts[i]->iconName) \
1709
.arg(i18nc("weather forecast", m_weatherData[source].forecasts[i]->shortForecast.toUtf8())) \
1710
.arg(m_weatherData[source].forecasts[i]->forecastTempHigh) \
1711
.arg(m_weatherData[source].forecasts[i]->forecastTempLow) \
1712
.arg(m_weatherData[source].forecasts[i]->popPrecent));
1713
//kDebug() << "i18n summary string: " << qPrintable(i18n(m_weatherData[source].forecasts[i]->shortForecast.toUtf8()));
1715
return forecastData;
1718
QMap<QString, QString> EnvCanadaIon::pressure(const QString& source) const
1720
QMap<QString, QString> pressureInfo;
1722
if (m_weatherData[source].pressure == 0) {
1723
pressureInfo.insert("pressure", i18n("N/A"));
1724
pressureInfo.insert("pressureUnit", QString::number(KUnitConversion::NoUnit));
1725
pressureInfo.insert("pressureTendency", "N/A");
1727
pressureInfo.insert("pressure", QString::number(m_weatherData[source].pressure, 'f', 1));
1728
pressureInfo.insert("pressureUnit", QString::number(KUnitConversion::Kilopascal));
1729
pressureInfo.insert("pressureTendency", i18nc("pressure tendency", m_weatherData[source].pressureTendency.toUtf8()));
1731
return pressureInfo;
1734
QMap<QString, QString> EnvCanadaIon::wind(const QString& source) const
1736
QMap<QString, QString> windInfo;
1738
// May not have any winds
1739
if (m_weatherData[source].windSpeed.isEmpty()) {
1740
windInfo.insert("windSpeed", i18n("N/A"));
1741
windInfo.insert("windUnit", QString::number(KUnitConversion::NoUnit));
1742
} else if (m_weatherData[source].windSpeed.toInt() == 0) {
1743
windInfo.insert("windSpeed", i18nc("wind speed", "Calm"));
1744
windInfo.insert("windUnit", QString::number(KUnitConversion::NoUnit));
1746
windInfo.insert("windSpeed", QString::number(m_weatherData[source].windSpeed.toInt()));
1747
windInfo.insert("windUnit", QString::number(KUnitConversion::KilometerPerHour));
1750
// May not always have gusty winds
1751
if (m_weatherData[source].windGust.isEmpty() || m_weatherData[source].windGust == 0) {
1752
windInfo.insert("windGust", i18n("N/A"));
1753
windInfo.insert("windGustUnit", QString::number(KUnitConversion::NoUnit));
1755
windInfo.insert("windGust", QString::number(m_weatherData[source].windGust.toInt()));
1756
windInfo.insert("windGustUnit", QString::number(KUnitConversion::KilometerPerHour));
1759
if (m_weatherData[source].windDirection.isEmpty() && m_weatherData[source].windSpeed.isEmpty()) {
1760
windInfo.insert("windDirection", i18n("N/A"));
1761
windInfo.insert("windDegrees", i18n("N/A"));
1762
} else if (m_weatherData[source].windSpeed.toInt() == 0) {
1763
windInfo.insert("windDirection", i18nc("wind direction - wind speed is too low to measure", "VR")); // Variable/calm
1765
windInfo.insert("windDirection", i18nc("wind direction", m_weatherData[source].windDirection.toUtf8()));
1766
windInfo.insert("windDegrees", m_weatherData[source].windDegrees);
1771
QMap<QString, QString> EnvCanadaIon::uvIndex(const QString& source) const
1773
QMap<QString, QString> uvInfo;
1775
if (m_weatherData[source].UVRating.isEmpty()) {
1776
uvInfo.insert("uvRating", i18n("N/A"));
1778
uvInfo.insert("uvRating", m_weatherData[source].UVRating);
1781
if (m_weatherData[source].UVIndex.isEmpty()) {
1782
uvInfo.insert("uvIndex", i18n("N/A"));
1784
uvInfo.insert("uvIndex", m_weatherData[source].UVIndex);
1790
QMap<QString, QString> EnvCanadaIon::regionalTemperatures(const QString& source) const
1792
QMap<QString, QString> regionalTempInfo;
1794
if (m_weatherData[source].normalHigh.isEmpty()) {
1795
regionalTempInfo.insert("normalHigh", i18n("N/A"));
1797
regionalTempInfo.insert("normalHigh", m_weatherData[source].normalHigh);
1800
if (m_weatherData[source].normalLow.isEmpty()) {
1801
regionalTempInfo.insert("normalLow", i18n("N/A"));
1803
regionalTempInfo.insert("normalLow", m_weatherData[source].normalLow);
1806
return regionalTempInfo;
1809
QMap<QString, QString> EnvCanadaIon::yesterdayWeather(const QString& source) const
1811
QMap<QString, QString> yesterdayInfo;
1813
if (m_weatherData[source].prevHigh.isEmpty()) {
1814
yesterdayInfo.insert("prevHigh", i18n("N/A"));
1816
yesterdayInfo.insert("prevHigh", m_weatherData[source].prevHigh);
1819
if (m_weatherData[source].prevLow.isEmpty()) {
1820
yesterdayInfo.insert("prevLow", i18n("N/A"));
1822
yesterdayInfo.insert("prevLow", m_weatherData[source].prevLow);
1825
if (m_weatherData[source].prevPrecipTotal == "Trace") {
1826
yesterdayInfo.insert("prevPrecip", i18nc("precipitation total, very little", "Trace"));
1827
return yesterdayInfo;
1830
if (m_weatherData[source].prevPrecipTotal.isEmpty()) {
1831
yesterdayInfo.insert("prevPrecip", i18n("N/A"));
1832
yesterdayInfo.insert("prevPrecipUnit", QString::number(KUnitConversion::NoUnit));
1834
yesterdayInfo.insert("prevPrecipTotal", m_weatherData[source].prevPrecipTotal);
1835
if (m_weatherData[source].prevPrecipType == "mm") {
1836
yesterdayInfo.insert("prevPrecipUnit", QString::number(KUnitConversion::Millimeter));
1837
} else if (m_weatherData[source].prevPrecipType == "cm") {
1838
yesterdayInfo.insert("prevPrecipUnit", QString::number(KUnitConversion::Centimeter));
1840
yesterdayInfo.insert("prevPrecipUnit", QString::number(KUnitConversion::NoUnit));
1844
return yesterdayInfo;
1847
QMap<QString, QString> EnvCanadaIon::sunriseSet(const QString& source) const
1849
QMap<QString, QString> sunInfo;
1851
if (m_weatherData[source].sunriseTimestamp.isEmpty()) {
1852
sunInfo.insert("sunrise", i18n("N/A"));
1854
sunInfo.insert("sunrise", m_weatherData[source].sunriseTimestamp);
1857
if (m_weatherData[source].sunsetTimestamp.isEmpty()) {
1858
sunInfo.insert("sunset", i18n("N/A"));
1860
sunInfo.insert("sunset", m_weatherData[source].sunsetTimestamp);
1866
QMap<QString, QString> EnvCanadaIon::moonriseSet(const QString& source) const
1868
QMap<QString, QString> moonInfo;
1870
if (m_weatherData[source].moonriseTimestamp.isEmpty()) {
1871
moonInfo.insert("moonrise", i18n("N/A"));
1873
moonInfo.insert("moonrise", m_weatherData[source].moonriseTimestamp);
1876
if (m_weatherData[source].moonsetTimestamp.isEmpty()) {
1877
moonInfo.insert("moonset", i18n("N/A"));
1879
moonInfo.insert("moonset", m_weatherData[source].moonsetTimestamp);
1885
QMap<QString, QString> EnvCanadaIon::weatherRecords(const QString& source) const
1887
QMap<QString, QString> recordInfo;
1889
if (m_weatherData[source].recordHigh == 0) {
1890
recordInfo.insert("recordHigh", i18n("N/A"));
1892
recordInfo.insert("recordHigh", QString("%1").arg(m_weatherData[source].recordHigh));
1895
if (m_weatherData[source].recordLow == 0) {
1896
recordInfo.insert("recordLow", i18n("N/A"));
1898
recordInfo.insert("recordLow", QString("%1").arg(m_weatherData[source].recordLow));
1901
if (m_weatherData[source].recordRain == 0) {
1902
recordInfo.insert("recordRain", i18n("N/A"));
1903
recordInfo.insert("recordRainUnit", QString::number(KUnitConversion::NoUnit));
1905
recordInfo.insert("recordRain", QString("%1").arg(m_weatherData[source].recordRain));
1906
recordInfo.insert("recordRainUnit", QString::number(KUnitConversion::Millimeter));
1909
if (m_weatherData[source].recordSnow == 0) {
1910
recordInfo.insert("recordSnow", i18n("N/A"));
1911
recordInfo.insert("recordSnowUnit", QString::number(KUnitConversion::NoUnit));
1913
recordInfo.insert("recordSnow", QString("%1").arg(m_weatherData[source].recordSnow));
1914
recordInfo.insert("recordSnowUnit", QString::number(KUnitConversion::Centimeter));
1920
#include "ion_envcan.moc"