1 /***************************************************************************
2 * Copyright (C) 2007 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"
24 class EnvCanadaIon::Private
: public QObject
33 QString territoryName
;
35 QString sourceOptions
;
40 QHash
<QString
, EnvCanadaIon::Private::XMLMapInfo
> m_place
;
41 QHash
<QString
, QString
> m_locations
;
46 // Weather information
47 QHash
<QString
, WeatherData
> m_weatherData
;
50 QMap
<KJob
*, QXmlStreamReader
*> m_jobXml
;
51 QMap
<KJob
*, QString
> m_jobList
;
52 QXmlStreamReader m_xmlSetup
;
54 KIO::TransferJob
*m_job
;
56 int m_timezoneType
; // Ion option: Timezone may be local time or UTC time
57 int m_measureType
; // Ion option: Units may be Metric or Imperial
62 EnvCanadaIon::EnvCanadaIon(QObject
*parent
, const QVariantList
&args
)
63 : IonInterface(parent
), d(new Private())
68 EnvCanadaIon::~EnvCanadaIon()
70 // Destroy each warning stored in a QVector
71 foreach(WeatherData item
, d
->m_weatherData
) {
72 foreach(WeatherData::WarningInfo
*warning
, item
.warnings
) {
77 foreach(WeatherData::ForecastInfo
*forecast
, item
.forecasts
) {
88 // Get the master list of locations to be parsed
89 void EnvCanadaIon::init()
91 // Get the real city XML URL so we can parse this
95 QStringList
EnvCanadaIon::validate(const QString
& source
) const
97 QStringList placeList
;
98 QHash
<QString
, QString
>::const_iterator it
= d
->m_locations
.constBegin();
99 while (it
!= d
->m_locations
.constEnd()) {
100 if (it
.value().toLower().contains(source
.toLower())) {
101 placeList
.append(QString("place|%1").arg(it
.value().split("|")[1]));
106 // Check if placeList is empty if so, return nothing.
107 if (placeList
.isEmpty()) {
108 return QStringList();
114 // Get a specific Ion's data
115 bool EnvCanadaIon::updateIonSource(const QString
& source
)
117 kDebug() << "updateIonSource() SOURCE: " << source
;
118 // We expect the applet to send the source in the following tokenization:
119 // ionname|validate|place_name - Triggers validation of place
120 // ionname|weather|place_name - Triggers receiving weather of place
122 QStringList sourceAction
= source
.split('|');
123 if (sourceAction
[1] == QString("validate")) {
124 kDebug() << "Initiate Validating of place: " << sourceAction
[2];
126 QStringList result
= validate(QString("%1|%2").arg(sourceAction
[0]).arg(sourceAction
[2]));
128 if (result
.size() == 1) {
129 setData(source
, "validate", QString("envcan|valid|single|%1").arg(result
.join("|")));
131 } else if (result
.size() > 1) {
132 setData(source
, "validate", QString("envcan|valid|multiple|%1").arg(result
.join("|")));
134 } else if (result
.size() == 0) {
135 setData(source
, "validate", QString("envcan|invalid|single|%1").arg(sourceAction
[2]));
139 } else if (sourceAction
[1] == QString("weather")) {
140 getXMLData(QString("%1|%2").arg(sourceAction
[0]).arg(sourceAction
[2]));
146 // Parses city list and gets the correct city based on ID number
147 void EnvCanadaIon::getXMLSetup()
150 d
->m_url
= new KUrl("http://dd.weatheroffice.ec.gc.ca/EC_sites/xml/siteList.xml");
152 KIO::TransferJob
*job
= KIO::get(d
->m_url
->url(), KIO::NoReload
, KIO::HideProgressInfo
);
155 connect(job
, SIGNAL(data(KIO::Job
*, const QByteArray
&)), this,
156 SLOT(setup_slotDataArrived(KIO::Job
*, const QByteArray
&)));
157 connect(job
, SIGNAL(result(KJob
*)), this, SLOT(setup_slotJobFinished(KJob
*)));
161 // Gets specific city XML data
162 void EnvCanadaIon::getXMLData(const QString
& source
)
165 url
= "http://dd.weatheroffice.ec.gc.ca/EC_sites/xml/" + d
->m_place
[source
].territoryName
+ "/" + d
->m_place
[source
].cityCode
+ "_e.xml";
167 kDebug() << "URL Location: " << url
.url();
169 d
->m_job
= KIO::get(url
.url(), KIO::Reload
, KIO::HideProgressInfo
);
170 d
->m_jobXml
.insert(d
->m_job
, new QXmlStreamReader
);
171 d
->m_jobList
.insert(d
->m_job
, source
);
174 connect(d
->m_job
, SIGNAL(data(KIO::Job
*, const QByteArray
&)), this,
175 SLOT(slotDataArrived(KIO::Job
*, const QByteArray
&)));
176 connect(d
->m_job
, SIGNAL(result(KJob
*)), this, SLOT(slotJobFinished(KJob
*)));
180 void EnvCanadaIon::setup_slotDataArrived(KIO::Job
*job
, const QByteArray
&data
)
184 if (data
.isEmpty()) {
189 d
->m_xmlSetup
.addData(data
);
192 void EnvCanadaIon::slotDataArrived(KIO::Job
*job
, const QByteArray
&data
)
195 if (data
.isEmpty() || !d
->m_jobXml
.contains(job
)) {
200 d
->m_jobXml
[job
]->addData(data
);
203 void EnvCanadaIon::slotJobFinished(KJob
*job
)
205 // Dual use method, if we're fetching location data to parse we need to do this first
206 readXMLData(d
->m_jobList
[job
], *d
->m_jobXml
[job
]);
207 d
->m_jobList
.remove(job
);
208 delete d
->m_jobXml
[job
];
209 d
->m_jobXml
.remove(job
);
212 void EnvCanadaIon::setup_slotJobFinished(KJob
*job
)
216 setInitialized(true);
219 // Parse the city list and store into a QMap
220 bool EnvCanadaIon::readXMLSetup()
223 while (!d
->m_xmlSetup
.atEnd()) {
224 d
->m_xmlSetup
.readNext();
226 if (d
->m_xmlSetup
.isStartElement()) {
228 // XML ID code to match filename
229 if (d
->m_xmlSetup
.name() == "site") {
230 d
->m_code
= d
->m_xmlSetup
.attributes().value("code").toString();
233 if (d
->m_xmlSetup
.name() == "nameEn") {
234 d
->m_cityName
= d
->m_xmlSetup
.readElementText(); // Name of cities
237 if (d
->m_xmlSetup
.name() == "provinceCode") {
238 d
->m_territory
= d
->m_xmlSetup
.readElementText(); // Provinces/Territory list
239 tmp
= "envcan|" + d
->m_cityName
+ ", " + d
->m_territory
; // Build the key name.
242 d
->m_place
[tmp
].cityCode
= d
->m_code
;
243 d
->m_place
[tmp
].territoryName
= d
->m_territory
;
244 d
->m_place
[tmp
].cityName
= d
->m_cityName
;
246 // Set the string list, we will use for the applet to display the available cities.
247 d
->m_locations
[tmp
] = tmp
;
252 return !d
->m_xmlSetup
.error();
255 WeatherData
EnvCanadaIon::parseWeatherSite(WeatherData
& data
, QXmlStreamReader
& xml
)
257 while (!xml
.atEnd()) {
260 if (xml
.isStartElement()) {
261 if (xml
.name() == "license") {
262 xml
.readElementText();
263 } else if (xml
.name() == "location") {
264 parseLocations(data
, xml
);
265 } else if (xml
.name() == "warnings") {
266 // Cleanup warning list on update
267 data
.warnings
.clear();
268 parseWarnings(data
, xml
);
269 } else if (xml
.name() == "currentConditions") {
270 parseConditions(data
, xml
);
271 } else if (xml
.name() == "forecastGroup") {
272 // Clean up forecast list on update
273 data
.forecasts
.clear();
274 parseWeatherForecast(data
, xml
);
275 } else if (xml
.name() == "yesterdayConditions") {
276 parseYesterdayWeather(data
, xml
);
277 } else if (xml
.name() == "riseSet") {
278 parseAstronomicals(data
, xml
);
279 } else if (xml
.name() == "almanac") {
280 parseWeatherRecords(data
, xml
);
282 parseUnknownElement(xml
);
289 // Parse Weather data main loop, from here we have to decend into each tag pair
290 bool EnvCanadaIon::readXMLData(const QString
& source
, QXmlStreamReader
& xml
)
293 data
.comforttemp
= "N/A";
294 data
.recordHigh
= 0.0;
295 data
.recordLow
= 0.0;
296 data
.shortTerritoryName
= d
->m_place
[source
].territoryName
;
297 while (!xml
.atEnd()) {
300 if (xml
.isEndElement()) {
304 if (xml
.isStartElement()) {
305 if (xml
.name() == "siteData") {
306 data
= parseWeatherSite(data
, xml
);
308 parseUnknownElement(xml
);
313 d
->m_weatherData
[source
] = data
;
314 updateWeather(source
);
318 void EnvCanadaIon::parseDateTime(WeatherData
& data
, QXmlStreamReader
& xml
, WeatherData::WarningInfo
*warning
)
321 Q_ASSERT(xml
.isStartElement() && xml
.name() == "dateTime");
323 // What kind of date info is this?
324 QString dateType
= xml
.attributes().value("name").toString();
325 QString dateZone
= xml
.attributes().value("zone").toString();
328 while (!xml
.atEnd()) {
331 if (xml
.isEndElement()) {
335 if (xml
.isStartElement()) {
336 if (dateType
== "xmlCreation") {
339 if (xml
.name() == "year") {
340 xml
.readElementText();
341 } else if (xml
.name() == "month") {
342 xml
.readElementText();
343 } else if (xml
.name() == "day") {
344 xml
.readElementText();
345 } else if (xml
.name() == "hour")
346 xml
.readElementText();
347 else if (xml
.name() == "minute")
348 xml
.readElementText();
349 else if (xml
.name() == "timeStamp")
350 xml
.readElementText();
351 else if (xml
.name() == "textSummary") {
352 if (timezone() && dateZone
== "UTC") {
353 // Which timestamp are we for?
355 if (dateType
== "eventIssue") {
357 warning
->timestamp
= xml
.readElementText();
359 } else if (dateType
== "observation") {
360 data
.obsTimestamp
= xml
.readElementText();
361 } else if (dateType
== "forecastIssue") {
362 data
.forecastTimestamp
= xml
.readElementText();
363 } else if (dateType
== "sunrise") {
364 data
.sunriseTimestamp
= xml
.readElementText();
365 } else if (dateType
== "sunset") {
366 data
.sunsetTimestamp
= xml
.readElementText();
367 } else if (dateType
== "moonrise") {
368 data
.moonriseTimestamp
= xml
.readElementText();
369 } else if (dateType
== "moonset") {
370 data
.moonsetTimestamp
= xml
.readElementText();
373 } else if (dateZone
!= "UTC") {
374 if (dateType
== "eventIssue") {
376 warning
->timestamp
= xml
.readElementText();
378 } else if (dateType
== "observation") {
379 data
.obsTimestamp
= xml
.readElementText();
380 } else if (dateType
== "forecastIssue") {
381 data
.forecastTimestamp
= xml
.readElementText();
382 } else if (dateType
== "sunrise") {
383 data
.sunriseTimestamp
= xml
.readElementText();
384 } else if (dateType
== "sunset") {
385 data
.sunsetTimestamp
= xml
.readElementText();
386 } else if (dateType
== "moonrise") {
387 data
.moonriseTimestamp
= xml
.readElementText();
388 } else if (dateType
== "moonset") {
389 data
.moonsetTimestamp
= xml
.readElementText();
397 void EnvCanadaIon::parseLocations(WeatherData
& data
, QXmlStreamReader
& xml
)
399 Q_ASSERT(xml
.isStartElement() && xml
.name() == "location");
401 while (!xml
.atEnd()) {
404 if (xml
.isEndElement()) {
408 if (xml
.isStartElement()) {
409 if (xml
.name() == "country") {
410 data
.countryName
= xml
.readElementText();
411 } else if (xml
.name() == "province" || xml
.name() == "territory") {
412 data
.longTerritoryName
= xml
.readElementText();
413 } else if (xml
.name() == "name") {
414 data
.cityName
= xml
.readElementText();
415 } else if (xml
.name() == "region") {
416 data
.regionName
= xml
.readElementText();
418 parseUnknownElement(xml
);
424 void EnvCanadaIon::parseWindInfo(WeatherData
& data
, QXmlStreamReader
& xml
)
426 Q_ASSERT(xml
.isStartElement() && xml
.name() == "wind");
428 while (!xml
.atEnd()) {
431 if (xml
.isEndElement()) {
435 if (xml
.isStartElement()) {
436 if (xml
.name() == "speed") {
437 data
.windSpeed
= xml
.readElementText();
438 } else if (xml
.name() == "gust") {
439 data
.windGust
= xml
.readElementText();
440 } else if (xml
.name() == "direction") {
441 data
.windDirection
= xml
.readElementText();
443 parseUnknownElement(xml
);
449 void EnvCanadaIon::parseConditions(WeatherData
& data
, QXmlStreamReader
& xml
)
452 Q_ASSERT(xml
.isStartElement() && xml
.name() == "currentConditions");
453 data
.temperature
= "N/A";
454 data
.dewpoint
= "N/A";
455 data
.condition
= "N/A";
456 data
.comforttemp
= "N/A";
457 data
.stationID
= "N/A";
459 data
.pressureTendency
= "N/A";
461 data
.humidity
= "N/A";
462 data
.windSpeed
= "N/A";
463 data
.windGust
= "N/A";
465 while (!xml
.atEnd()) {
468 if (xml
.isEndElement() && xml
.name() == "currentConditions")
471 if (xml
.isStartElement()) {
472 if (xml
.name() == "station") {
473 data
.stationID
= xml
.attributes().value("code").toString();
474 } else if (xml
.name() == "dateTime") {
475 parseDateTime(data
, xml
);
476 } else if (xml
.name() == "condition") {
477 data
.condition
= xml
.readElementText();
478 } else if (xml
.name() == "temperature") {
479 data
.temperature
= xml
.readElementText();;
480 } else if (xml
.name() == "dewpoint") {
481 data
.dewpoint
= xml
.readElementText();
482 } else if (xml
.name() == "humidex" || xml
.name() == "windChill") {
483 data
.comforttemp
= xml
.readElementText();
484 } else if (xml
.name() == "pressure") {
485 data
.pressureTendency
= xml
.attributes().value("tendency").toString();
486 if (data
.pressureTendency
.isEmpty()) {
487 data
.pressureTendency
= "steady";
489 data
.pressure
= xml
.readElementText().toFloat();
490 } else if (xml
.name() == "visibility") {
491 data
.visibility
= xml
.readElementText().toFloat();
492 } else if (xml
.name() == "relativeHumidity") {
493 data
.humidity
= xml
.readElementText();
494 } else if (xml
.name() == "wind") {
495 parseWindInfo(data
, xml
);
498 // parseUnknownElement(xml);
504 void EnvCanadaIon::parseWarnings(WeatherData
&data
, QXmlStreamReader
& xml
)
506 WeatherData::WarningInfo
* warning
= new WeatherData::WarningInfo
;
508 Q_ASSERT(xml
.isStartElement() && xml
.name() == "warnings");
509 QString warningURL
= xml
.attributes().value("url").toString();
510 while (!xml
.atEnd()) {
513 if (xml
.isEndElement() && xml
.name() == "warnings") {
517 if (xml
.isStartElement()) {
518 if (xml
.name() == "dateTime") {
519 parseDateTime(data
, xml
, warning
);
520 if (!warning
->timestamp
.isEmpty() && !warning
->url
.isEmpty()) {
521 data
.warnings
.append(warning
);
522 warning
= new WeatherData::WarningInfo
;
524 } else if (xml
.name() == "event") {
525 // Append new event to list.
526 warning
->url
= warningURL
;
527 warning
->type
= xml
.attributes().value("type").toString();
528 warning
->priority
= xml
.attributes().value("priority").toString();
529 warning
->description
= xml
.attributes().value("description").toString();
531 if (xml
.name() != "dateTime") {
532 parseUnknownElement(xml
);
541 void EnvCanadaIon::parseWeatherForecast(WeatherData
& data
, QXmlStreamReader
& xml
)
543 WeatherData::ForecastInfo
* forecast
= new WeatherData::ForecastInfo
;
544 Q_ASSERT(xml
.isStartElement() && xml
.name() == "forecastGroup");
546 while (!xml
.atEnd()) {
549 if (xml
.isEndElement() && xml
.name() == "forecastGroup") {
553 if (xml
.isStartElement()) {
554 if (xml
.name() == "dateTime") {
555 parseDateTime(data
, xml
);
556 } else if (xml
.name() == "regionalNormals") {
557 parseRegionalNormals(data
, xml
);
558 } else if (xml
.name() == "forecast") {
559 parseForecast(data
, xml
, forecast
);
560 forecast
= new WeatherData::ForecastInfo
;
562 parseUnknownElement(xml
);
569 void EnvCanadaIon::parseRegionalNormals(WeatherData
& data
, QXmlStreamReader
& xml
)
571 Q_ASSERT(xml
.isStartElement() && xml
.name() == "regionalNormals");
573 while (!xml
.atEnd()) {
576 if (xml
.isEndElement()) {
580 if (xml
.isStartElement()) {
581 if (xml
.name() == "textSummary") {
582 xml
.readElementText();
583 } else if (xml
.name() == "temperature" && xml
.attributes().value("class") == "high") {
584 data
.normalHigh
= xml
.readElementText();
585 } else if (xml
.name() == "temperature" && xml
.attributes().value("class") == "low") {
586 data
.normalLow
= xml
.readElementText();
592 void EnvCanadaIon::parseForecast(WeatherData
& data
, QXmlStreamReader
& xml
, WeatherData::ForecastInfo
*forecast
)
595 Q_ASSERT(xml
.isStartElement() && xml
.name() == "forecast");
597 while (!xml
.atEnd()) {
600 if (xml
.isEndElement() && xml
.name() == "forecast") {
601 data
.forecasts
.append(forecast
);
605 if (xml
.isStartElement()) {
606 if (xml
.name() == "period") {
607 forecast
->forecastPeriod
= xml
.readElementText();
608 } else if (xml
.name() == "textSummary") {
609 forecast
->forecastSummary
= xml
.readElementText();
610 } else if (xml
.name() == "abbreviatedForecast") {
611 parseShortForecast(forecast
, xml
);
612 } else if (xml
.name() == "temperatures") {
613 parseForecastTemperatures(forecast
, xml
);
614 } else if (xml
.name() == "winds") {
615 parseWindForecast(forecast
, xml
);
616 } else if (xml
.name() == "precipitation") {
617 parsePrecipitationForecast(forecast
, xml
);
618 } else if (xml
.name() == "uv") {
619 data
.UVRating
= xml
.attributes().value("category").toString();
620 parseUVIndex(data
, xml
);
621 // else if (xml.name() == "frost") { FIXME: Wait until winter to see what this looks like.
622 // parseFrost(xml, forecast);
624 if (xml
.name() != "forecast") {
625 parseUnknownElement(xml
);
632 void EnvCanadaIon::parseShortForecast(WeatherData::ForecastInfo
*forecast
, QXmlStreamReader
& xml
)
634 Q_ASSERT(xml
.isStartElement() && xml
.name() == "abbreviatedForecast");
636 while (!xml
.atEnd()) {
639 if (xml
.isEndElement() && xml
.name() == "abbreviatedForecast") {
643 if (xml
.isStartElement()) {
644 if (xml
.name() == "pop") {
645 forecast
->popPrecent
= xml
.readElementText();
647 if (xml
.name() == "textSummary") {
648 forecast
->shortForecast
= xml
.readElementText();
654 void EnvCanadaIon::parseUVIndex(WeatherData
& data
, QXmlStreamReader
& xml
)
656 Q_ASSERT(xml
.isStartElement() && xml
.name() == "uv");
658 while (!xml
.atEnd()) {
661 if (xml
.isEndElement() && xml
.name() == "uv") {
665 if (xml
.isStartElement()) {
666 if (xml
.name() == "index") {
667 data
.UVIndex
= xml
.readElementText();
669 if (xml
.name() == "textSummary") {
670 xml
.readElementText();
676 void EnvCanadaIon::parseForecastTemperatures(WeatherData::ForecastInfo
*forecast
, QXmlStreamReader
& xml
)
678 Q_ASSERT(xml
.isStartElement() && xml
.name() == "temperatures");
680 while (!xml
.atEnd()) {
683 if (xml
.isEndElement() && xml
.name() == "temperatures") {
687 if (xml
.isStartElement()) {
688 if (xml
.name() == "temperature" && xml
.attributes().value("class") == "low") {
689 forecast
->forecastTempLow
= xml
.readElementText();
690 } else if (xml
.name() == "temperature" && xml
.attributes().value("class") == "high") {
691 forecast
->forecastTempHigh
= xml
.readElementText();
692 } else if (xml
.name() == "textSummary") {
693 xml
.readElementText();
699 void EnvCanadaIon::parsePrecipitationForecast(WeatherData::ForecastInfo
*forecast
, QXmlStreamReader
& xml
)
701 Q_ASSERT(xml
.isStartElement() && xml
.name() == "precipitation");
703 while (!xml
.atEnd()) {
706 if (xml
.isEndElement() && xml
.name() == "precipitation") {
710 if (xml
.isStartElement()) {
711 //kDebug() << "parsePrecipitationForecast() ====> TAG: " << xml.name().toString();
712 if (xml
.name() == "textSummary") {
713 forecast
->precipForecast
= xml
.readElementText();
714 } else if (xml
.name() == "precipType") {
715 forecast
->precipType
= xml
.readElementText();
716 } else if (xml
.name() == "accumulation") {
717 parsePrecipTotals(forecast
, xml
);
723 void EnvCanadaIon::parsePrecipTotals(WeatherData::ForecastInfo
*forecast
, QXmlStreamReader
& xml
)
725 Q_ASSERT(xml
.isStartElement() && xml
.name() == "accumulation");
727 while (!xml
.atEnd()) {
730 if (xml
.isEndElement() && xml
.name() == "accumulation") {
734 if (xml
.name() == "name") {
735 xml
.readElementText();
736 } else if (xml
.name() == "amount") {
737 forecast
->precipTotalExpected
= xml
.readElementText();
742 void EnvCanadaIon::parseWindForecast(WeatherData::ForecastInfo
*forecast
, QXmlStreamReader
& xml
)
744 Q_ASSERT(xml
.isStartElement() && xml
.name() == "winds");
746 while (!xml
.atEnd()) {
749 if (xml
.isEndElement() && xml
.name() == "winds") {
753 if (xml
.isStartElement()) {
754 if (xml
.name() == "textSummary") {
755 forecast
->windForecast
= xml
.readElementText();
757 if (xml
.name() != "winds") {
758 parseUnknownElement(xml
);
765 void EnvCanadaIon::parseYesterdayWeather(WeatherData
& data
, QXmlStreamReader
& xml
)
767 Q_ASSERT(xml
.isStartElement() && xml
.name() == "yesterdayConditions");
769 while (!xml
.atEnd()) {
772 if (xml
.isEndElement()) {
776 if (xml
.isStartElement()) {
777 if (xml
.name() == "temperature" && xml
.attributes().value("class") == "high") {
778 data
.prevHigh
= xml
.readElementText();
779 } else if (xml
.name() == "temperature" && xml
.attributes().value("class") == "low") {
780 data
.prevLow
= xml
.readElementText();
781 } else if (xml
.name() == "precip") {
782 data
.prevPrecipType
= xml
.attributes().value("units").toString();
783 if (data
.prevPrecipType
.isEmpty()) {
784 data
.prevPrecipType
= "N/A";
786 data
.prevPrecipTotal
= xml
.readElementText();
792 void EnvCanadaIon::parseWeatherRecords(WeatherData
& data
, QXmlStreamReader
& xml
)
794 Q_ASSERT(xml
.isStartElement() && xml
.name() == "almanac");
796 while (!xml
.atEnd()) {
799 if (xml
.isEndElement() && xml
.name() == "almanac") {
803 if (xml
.isStartElement()) {
804 if (xml
.name() == "temperature" && xml
.attributes().value("class") == "extremeMax") {
805 data
.recordHigh
= xml
.readElementText().toFloat();
806 } else if (xml
.name() == "temperature" && xml
.attributes().value("class") == "extremeMin") {
807 data
.recordLow
= xml
.readElementText().toFloat();
808 } else if (xml
.name() == "precipitation" && xml
.attributes().value("class") == "extremeRainfall") {
809 data
.recordRain
= xml
.readElementText().toFloat();
810 } else if (xml
.name() == "precipitation" && xml
.attributes().value("class") == "extremeSnowfall") {
811 data
.recordSnow
= xml
.readElementText().toFloat();
817 void EnvCanadaIon::parseAstronomicals(WeatherData
& data
, QXmlStreamReader
& xml
)
819 Q_ASSERT(xml
.isStartElement() && xml
.name() == "riseSet");
821 while (!xml
.atEnd()) {
824 if (xml
.isEndElement() && xml
.name() == "riseSet") {
828 if (xml
.isStartElement()) {
829 if (xml
.name() == "disclaimer") {
830 xml
.readElementText();
831 } else if (xml
.name() == "dateTime") {
832 parseDateTime(data
, xml
);
838 // handle when no XML tag is found
839 void EnvCanadaIon::parseUnknownElement(QXmlStreamReader
& xml
)
842 while (!xml
.atEnd()) {
845 if (xml
.isEndElement()) {
849 if (xml
.isStartElement()) {
850 parseUnknownElement(xml
);
855 void EnvCanadaIon::setMeasureUnit(const QString
& unitType
)
857 d
->m_measureType
= unitType
.toInt();
860 void EnvCanadaIon::setTimezoneFormat(const QString
& tz
)
862 d
->m_timezoneType
= tz
.toInt(); // Boolean
865 bool EnvCanadaIon::metricUnit()
867 if (d
->m_measureType
== KLocale::Metric
) {
875 bool EnvCanadaIon::timezone()
877 if (d
->m_timezoneType
) {
881 // Not UTC, local time
885 void EnvCanadaIon::updateWeather(const QString
& source
)
887 QMap
<QString
, QString
> dataFields
;
888 QStringList fieldList
;
889 QVector
<QString
> forecastList
;
892 QString weatherSource
= source
;
893 weatherSource
.replace("envcan|", "envcan|weather|");
895 setData(weatherSource
, "Country", country(source
));
896 setData(weatherSource
, "Place", QString("%1, %2").arg(city(source
)).arg(territory(source
)));
897 setData(weatherSource
, "Region", region(source
));
898 setData(weatherSource
, "Station", station(source
));
900 // Real weather - Current conditions
901 setData(weatherSource
, "Observation Period", observationTime(source
));
902 setData(weatherSource
, "Current Conditions", condition(source
));
903 dataFields
= temperature(source
);
904 setData(weatherSource
, "Temperature", dataFields
["temperature"]);
906 // Do we have a comfort temperature? if so display it
907 if (dataFields
["comfortTemperature"] != "N/A" && !dataFields
["comfortTemperature"].isEmpty()) {
908 if (dataFields
["comfortTemperature"].toFloat() <= 0 || (dataFields
["comfortTemperature"].toFloat() <= 32 && !metricUnit())) {
909 setData(weatherSource
, "Windchill", QString("%1%2").arg(dataFields
["comfortTemperature"]).arg(QChar(176)));
910 setData(weatherSource
, "Humidex", "N/A");
912 setData(weatherSource
, "Humidex", QString("%1%2").arg(dataFields
["comfortTemperature"]).arg(QChar(176)));
913 setData(weatherSource
, "Windchill", "N/A");
916 setData(weatherSource
, "Windchill", "N/A");
917 setData(weatherSource
, "Humidex", "N/A");
920 setData(weatherSource
, "Temperature Unit", dataFields
["temperatureUnit"]);
922 setData(weatherSource
, "Dewpoint", dewpoint(source
));
923 if (dewpoint(source
) != "N/A") {
924 setData(weatherSource
, "Dewpoint Unit", dataFields
["temperatureUnit"]);
927 dataFields
= pressure(source
);
928 setData(weatherSource
, "Pressure", dataFields
["pressure"]);
930 if (dataFields
["pressure"] != "N/A") {
931 setData(weatherSource
, "Pressure Tendency", dataFields
["pressureTendency"]);
932 setData(weatherSource
, "Pressure Unit", dataFields
["pressureUnit"]);
935 dataFields
= visibility(source
);
936 setData(weatherSource
, "Visibility", dataFields
["visibility"]);
937 if (dataFields
["visibility"] != "N/A") {
938 setData(weatherSource
, "Visibility Unit", dataFields
["visibilityUnit"]);
941 setData(weatherSource
, "Humidity", humidity(source
));
943 dataFields
= wind(source
);
944 setData(weatherSource
, "Wind Speed", dataFields
["windSpeed"]);
945 if (dataFields
["windSpeed"] != "N/A") {
946 setData(weatherSource
, "Wind Speed Unit", dataFields
["windUnit"]);
948 setData(weatherSource
, "Wind Gust", dataFields
["windGust"]);
949 setData(weatherSource
, "Wind Direction", dataFields
["windDirection"]);
950 setData(weatherSource
, "Wind Gust Unit", dataFields
["windGustUnit"]);
952 dataFields
= regionalTemperatures(source
);
953 setData(weatherSource
, "Normal High", dataFields
["normalHigh"]);
954 setData(weatherSource
, "Normal Low", dataFields
["normalLow"]);
955 if (dataFields
["normalHigh"] != "N/A" && dataFields
["normalLow"] != "N/A") {
956 setData(weatherSource
, "Regional Temperature Unit", dataFields
["regionalTempUnit"]);
959 // Check if UV index is available for the location
960 dataFields
= uvIndex(source
);
961 setData(weatherSource
, "UV Index", dataFields
["uvIndex"]);
962 if (dataFields
["uvIndex"] != "N/A") {
963 setData(weatherSource
, "UV Rating", dataFields
["uvRating"]);
966 dataFields
= warnings(source
);
967 // Check if we have warnings or watches
969 for (int i
= 0; i
< EnvCanadaIon::MAX_WARNINGS
; i
++) {
970 if (!dataFields
[QString("watch %1").arg(i
)].isEmpty()) {
971 fieldList
= dataFields
[QString("watch %1").arg(i
)].split('|');
972 setData(weatherSource
, QString("Watch Priority %1").arg(i
), fieldList
[0]);
973 setData(weatherSource
, QString("Watch Description %1").arg(i
), fieldList
[1]);
974 setData(weatherSource
, QString("Watch Info %1").arg(i
), fieldList
[2]);
975 setData(weatherSource
, QString("Watch Timestamp %1").arg(i
), fieldList
[3]);
977 if (!dataFields
[QString("warning %1").arg(i
)].isEmpty()) {
978 fieldList
= dataFields
[QString("warning %1").arg(i
)].split('|');
979 setData(weatherSource
, QString("Warning Priority %1").arg(i
), fieldList
[0]);
980 setData(weatherSource
, QString("Warning Description %1").arg(i
), fieldList
[1]);
981 setData(weatherSource
, QString("Warning Info %1").arg(i
), fieldList
[2]);
982 setData(weatherSource
, QString("Warning Timestamp %1").arg(i
), fieldList
[3]);
986 forecastList
= forecasts(source
);
987 foreach(QString forecastItem
, forecastList
) {
988 fieldList
= forecastItem
.split('|');
990 // TODO: We don't convert the wind format (Knots, meteres per second, bft) for the Long Forecast yet. These are not used in the applet (for now).
992 setData(weatherSource
, QString("Short Forecast Day %1").arg(i
), QString("%1|%2|%3|%4|%5") \
993 .arg(fieldList
[0]).arg(fieldList
[1]).arg(fieldList
[3]).arg(fieldList
[4]).arg(fieldList
[5]));
995 setData(weatherSource
, QString("Long Forecast Day %1").arg(i
), QString("%1|%2|%3|%4|%5|%6|%7|%8") \
996 .arg(fieldList
[0]).arg(fieldList
[2]).arg(fieldList
[3]).arg(fieldList
[4]).arg(fieldList
[6]) \
997 .arg(fieldList
[7]).arg(fieldList
[8]).arg(fieldList
[9]));
999 setData(weatherSource
, QString("Short Forecast Day %1").arg(i
), QString("%1|%2|%3|%4|%5") \
1000 .arg(fieldList
[0]).arg(fieldList
[1]).arg(fieldList
[3] == "N/A" ? "N/A" : \
1001 QString::number(WeatherFormula::celsiusToF(fieldList
[3].toFloat()), 'd', 0)) \
1002 .arg(fieldList
[4] == "N/A" ? "N/A" : QString::number(WeatherFormula::celsiusToF(fieldList
[4].toFloat()), 'd', 0)).arg(fieldList
[5]));
1004 setData(weatherSource
, QString("Long Forecast Day %1").arg(i
), QString("%1|%2|%3|%4|%5|%6|%7|%8") \
1005 .arg(fieldList
[0]).arg(fieldList
[2]).arg(fieldList
[3] == "N/A" ? "N/A" : \
1006 QString::number(WeatherFormula::celsiusToF(fieldList
[3].toFloat()), 'd', 0)) \
1007 .arg(fieldList
[4] == "N/A" ? "N/A" : QString::number(WeatherFormula::celsiusToF(fieldList
[4].toFloat()), 'd', 0)).arg(fieldList
[6]).arg(fieldList
[7]) \
1008 .arg(fieldList
[8]).arg(fieldList
[9]));
1014 dataFields
= yesterdayWeather(source
);
1015 setData(weatherSource
, "Yesterday High", dataFields
["prevHigh"]);
1016 setData(weatherSource
, "Yesterday Low", dataFields
["prevLow"]);
1018 if (dataFields
["prevHigh"] != "N/A" && dataFields
["prevLow"] != "N/A") {
1019 setData(weatherSource
, "Yesterday Temperature Unit", dataFields
["yesterdayTempUnit"]);
1022 setData(weatherSource
, "Yesterday Precip Total", dataFields
["prevPrecip"]);
1023 setData(weatherSource
, "Yesterday Precip Unit", dataFields
["prevPrecipUnit"]);
1025 dataFields
= sunriseSet(source
);
1026 setData(weatherSource
, "Sunrise At", dataFields
["sunrise"]);
1027 setData(weatherSource
, "Sunset At", dataFields
["sunset"]);
1029 dataFields
= moonriseSet(source
);
1030 setData(weatherSource
, "Moonrise At", dataFields
["moonrise"]);
1031 setData(weatherSource
, "Moonset At", dataFields
["moonset"]);
1033 dataFields
= weatherRecords(source
);
1034 setData(weatherSource
, "Record High Temperature", dataFields
["recordHigh"]);
1035 setData(weatherSource
, "Record Low Temperature", dataFields
["recordLow"]);
1036 if (dataFields
["recordHigh"] != "N/A" && dataFields
["recordLow"] != "N/A") {
1037 setData(weatherSource
, "Record Temperature Unit", dataFields
["recordTempUnit"]);
1040 setData(weatherSource
, "Record Rainfall", dataFields
["recordRain"]);
1041 setData(weatherSource
, "Record Rainfall Unit", dataFields
["recordRainUnit"]);
1042 setData(weatherSource
, "Record Snowfall", dataFields
["recordSnow"]);
1043 setData(weatherSource
, "Record Snowfall Unit", dataFields
["recordSnowUnit"]);
1045 setData(weatherSource
, "Credit", "Meteorological data is provided by Environment Canada");
1048 QString
EnvCanadaIon::country(const QString
& source
)
1050 return d
->m_weatherData
[source
].countryName
;
1052 QString
EnvCanadaIon::territory(const QString
& source
)
1054 return d
->m_weatherData
[source
].shortTerritoryName
;
1056 QString
EnvCanadaIon::city(const QString
& source
)
1058 return d
->m_weatherData
[source
].cityName
;
1060 QString
EnvCanadaIon::region(const QString
& source
)
1062 return d
->m_weatherData
[source
].regionName
;
1064 QString
EnvCanadaIon::station(const QString
& source
)
1066 if (!d
->m_weatherData
[source
].stationID
.isEmpty()) {
1067 return d
->m_weatherData
[source
].stationID
.toUpper();
1070 return QString("N/A");
1073 QString
EnvCanadaIon::observationTime(const QString
& source
)
1075 return d
->m_weatherData
[source
].obsTimestamp
;
1077 QString
EnvCanadaIon::condition(const QString
& source
)
1079 if (d
->m_weatherData
[source
].condition
.isEmpty()) {
1080 d
->m_weatherData
[source
].condition
= "N/A";
1082 return d
->m_weatherData
[source
].condition
;
1085 QString
EnvCanadaIon::dewpoint(const QString
& source
)
1088 if (!d
->m_weatherData
[source
].dewpoint
.isEmpty()) {
1089 return QString::number(d
->m_weatherData
[source
].dewpoint
.toFloat(), 'f', 1);
1093 if (!d
->m_weatherData
[source
].dewpoint
.isEmpty()) {
1094 return QString::number(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].dewpoint
.toFloat()), 'f', 1);
1097 return QString("N/A");
1100 QString
EnvCanadaIon::humidity(const QString
& source
)
1102 if (!d
->m_weatherData
[source
].humidity
.isEmpty()) {
1103 return QString("%1%").arg(d
->m_weatherData
[source
].humidity
);
1105 return QString("N/A");
1108 QMap
<QString
, QString
> EnvCanadaIon::visibility(const QString
& source
)
1110 QMap
<QString
, QString
> visibilityInfo
;
1112 if (!d
->m_weatherData
[source
].visibility
== 0) {
1114 visibilityInfo
.insert("visibility", QString::number(d
->m_weatherData
[source
].visibility
, 'f', 1));
1115 visibilityInfo
.insert("visibilityUnit", "km");
1117 visibilityInfo
.insert("visibility", QString::number(WeatherFormula::kilometersToMI(d
->m_weatherData
[source
].visibility
), 'f', 2));
1118 visibilityInfo
.insert("visibilityUnit", "mi");
1121 visibilityInfo
.insert("visibility", "N/A");
1123 return visibilityInfo
;
1126 QMap
<QString
, QString
> EnvCanadaIon::temperature(const QString
& source
)
1128 QMap
<QString
, QString
> temperatureInfo
;
1130 if (!d
->m_weatherData
[source
].temperature
.isEmpty()) {
1131 temperatureInfo
.insert("temperature", QString::number(d
->m_weatherData
[source
].temperature
.toFloat(), 'f', 1));
1133 temperatureInfo
.insert("temperatureUnit", QString("%1C").arg(QChar(176)));
1135 if (!d
->m_weatherData
[source
].temperature
.isEmpty()) {
1136 temperatureInfo
.insert("temperature", QString::number(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].temperature
.toFloat()), 'f', 1));
1138 temperatureInfo
.insert("temperature", "N/A");
1140 temperatureInfo
.insert("temperatureUnit", QString("%1F").arg(QChar(176)));
1142 temperatureInfo
.insert("comfortTemperature", "N/A");
1144 if (d
->m_weatherData
[source
].comforttemp
!= "N/A") {
1146 temperatureInfo
.insert("comfortTemperature", d
->m_weatherData
[source
].comforttemp
);
1148 if (!d
->m_weatherData
[source
].comforttemp
.isEmpty()) {
1149 temperatureInfo
.insert("comfortTemperature", QString::number(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].comforttemp
.toFloat()), 'f', 1));
1153 return temperatureInfo
;
1156 QMap
<QString
, QString
> EnvCanadaIon::warnings(const QString
& source
)
1158 QMap
<QString
, QString
> warningData
;
1160 for (int i
= 0; i
< d
->m_weatherData
[source
].warnings
.size(); ++i
) {
1161 if (d
->m_weatherData
[source
].warnings
[i
]->type
== "watch") {
1162 warnType
= QString("watch %1").arg(i
);
1164 warnType
= QString("warning %1").arg(i
);
1166 warningData
[warnType
] = QString("%1|%2|%3|%4").arg(d
->m_weatherData
[source
].warnings
[i
]->priority
) \
1167 .arg(d
->m_weatherData
[source
].warnings
[i
]->description
) \
1168 .arg(d
->m_weatherData
[source
].warnings
[i
]->url
) \
1169 .arg(d
->m_weatherData
[source
].warnings
[i
]->timestamp
);
1174 QVector
<QString
> EnvCanadaIon::forecasts(const QString
& source
)
1176 QVector
<QString
> forecastData
;
1178 // Do some checks for empty data
1179 for (int i
= 0; i
< d
->m_weatherData
[source
].forecasts
.size(); ++i
) {
1180 if (d
->m_weatherData
[source
].forecasts
[i
]->forecastPeriod
.isEmpty()) {
1181 d
->m_weatherData
[source
].forecasts
[i
]->forecastPeriod
= "N/A";
1183 if (d
->m_weatherData
[source
].forecasts
[i
]->shortForecast
.isEmpty()) {
1184 d
->m_weatherData
[source
].forecasts
[i
]->shortForecast
= "N/A";
1186 if (d
->m_weatherData
[source
].forecasts
[i
]->forecastSummary
.isEmpty()) {
1187 d
->m_weatherData
[source
].forecasts
[i
]->forecastSummary
= "N/A";
1189 if (d
->m_weatherData
[source
].forecasts
[i
]->forecastTempHigh
.isEmpty()) {
1190 d
->m_weatherData
[source
].forecasts
[i
]->forecastTempHigh
= "N/A";
1192 if (d
->m_weatherData
[source
].forecasts
[i
]->forecastTempLow
.isEmpty()) {
1193 d
->m_weatherData
[source
].forecasts
[i
]->forecastTempLow
= "N/A";
1195 if (d
->m_weatherData
[source
].forecasts
[i
]->popPrecent
.isEmpty()) {
1196 d
->m_weatherData
[source
].forecasts
[i
]->popPrecent
= "N/A";
1198 if (d
->m_weatherData
[source
].forecasts
[i
]->windForecast
.isEmpty()) {
1199 d
->m_weatherData
[source
].forecasts
[i
]->windForecast
= "N/A";
1201 if (d
->m_weatherData
[source
].forecasts
[i
]->precipForecast
.isEmpty()) {
1202 d
->m_weatherData
[source
].forecasts
[i
]->precipForecast
= "N/A";
1204 if (d
->m_weatherData
[source
].forecasts
[i
]->precipType
.isEmpty()) {
1205 d
->m_weatherData
[source
].forecasts
[i
]->precipType
= "N/A";
1207 if (d
->m_weatherData
[source
].forecasts
[i
]->precipTotalExpected
.isEmpty()) {
1208 d
->m_weatherData
[source
].forecasts
[i
]->precipTotalExpected
= "N/A";
1212 for (int i
= 0; i
< d
->m_weatherData
[source
].forecasts
.size(); ++i
) {
1213 forecastData
.append(QString("%1|%2|%3|%4|%5|%6|%7|%8|%9|%10") \
1214 .arg(d
->m_weatherData
[source
].forecasts
[i
]->forecastPeriod
) \
1215 .arg(d
->m_weatherData
[source
].forecasts
[i
]->shortForecast
) \
1216 .arg(d
->m_weatherData
[source
].forecasts
[i
]->forecastSummary
) \
1217 .arg(d
->m_weatherData
[source
].forecasts
[i
]->forecastTempHigh
) \
1218 .arg(d
->m_weatherData
[source
].forecasts
[i
]->forecastTempLow
) \
1219 .arg(d
->m_weatherData
[source
].forecasts
[i
]->popPrecent
) \
1220 .arg(d
->m_weatherData
[source
].forecasts
[i
]->windForecast
) \
1221 .arg(d
->m_weatherData
[source
].forecasts
[i
]->precipForecast
) \
1222 .arg(d
->m_weatherData
[source
].forecasts
[i
]->precipType
) \
1223 .arg(d
->m_weatherData
[source
].forecasts
[i
]->precipTotalExpected
));
1225 return forecastData
;
1228 QMap
<QString
, QString
> EnvCanadaIon::pressure(const QString
& source
)
1230 QMap
<QString
, QString
> pressureInfo
;
1232 if (d
->m_weatherData
[source
].pressure
== 0) {
1233 pressureInfo
.insert("pressure", "N/A");
1234 return pressureInfo
;
1237 pressureInfo
.insert("pressure", QString::number(d
->m_weatherData
[source
].pressure
, 'f', 1));
1238 pressureInfo
.insert("pressureUnit", "kPa");
1240 pressureInfo
.insert("pressure", QString::number(WeatherFormula::kilopascalsToInches(d
->m_weatherData
[source
].pressure
), 'f', 2));
1241 pressureInfo
.insert("pressureUnit", "in");
1243 pressureInfo
.insert("pressureTendency", d
->m_weatherData
[source
].pressureTendency
);
1245 return pressureInfo
;
1248 QMap
<QString
, QString
> EnvCanadaIon::wind(const QString
& source
)
1250 QMap
<QString
, QString
> windInfo
;
1252 // May not have any winds
1253 if (d
->m_weatherData
[source
].windSpeed
.isEmpty()) {
1254 windInfo
.insert("windSpeed", "N/A");
1255 windInfo
.insert("windUnit", "N/A");
1256 } else if (d
->m_weatherData
[source
].windSpeed
.toInt() == 0) {
1257 windInfo
.insert("windSpeed", "Calm");
1258 windInfo
.insert("windUnit", "N/A");
1261 windInfo
.insert("windSpeed", QString::number(d
->m_weatherData
[source
].windSpeed
.toInt()));
1262 windInfo
.insert("windUnit", "km/h");
1264 windInfo
.insert("windSpeed", QString::number(WeatherFormula::kilometersToMI(d
->m_weatherData
[source
].windSpeed
.toInt()), 'f', 1));
1265 windInfo
.insert("windUnit", "mph");
1269 // May not always have gusty winds
1270 if (d
->m_weatherData
[source
].windGust
.isEmpty()) {
1271 windInfo
.insert("windGust", "N/A");
1272 windInfo
.insert("windGustUnit", "N/A");
1275 windInfo
.insert("windGust", QString::number(d
->m_weatherData
[source
].windGust
.toInt()));
1276 windInfo
.insert("windGustUnit", "km/h");
1278 windInfo
.insert("windGust", QString::number(WeatherFormula::kilometersToMI(d
->m_weatherData
[source
].windGust
.toInt()), 'f', 1));
1279 windInfo
.insert("windGustUnit", "mph");
1283 if (d
->m_weatherData
[source
].windDirection
.isEmpty() && d
->m_weatherData
[source
].windSpeed
.isEmpty()) {
1284 windInfo
.insert("windDirection", "N/A");
1285 } else if (d
->m_weatherData
[source
].windSpeed
.toInt() == 0) {
1286 windInfo
.insert("windDirection", "VR");
1288 windInfo
.insert("windDirection", d
->m_weatherData
[source
].windDirection
);
1293 QMap
<QString
, QString
> EnvCanadaIon::uvIndex(const QString
& source
)
1295 QMap
<QString
, QString
> uvInfo
;
1297 if (d
->m_weatherData
[source
].UVRating
.isEmpty()) {
1298 uvInfo
.insert("uvRating", "N/A");
1300 uvInfo
.insert("uvRating", d
->m_weatherData
[source
].UVRating
);
1303 if (d
->m_weatherData
[source
].UVIndex
.isEmpty()) {
1304 uvInfo
.insert("uvIndex", "N/A");
1306 uvInfo
.insert("uvIndex", d
->m_weatherData
[source
].UVIndex
);
1312 QMap
<QString
, QString
> EnvCanadaIon::regionalTemperatures(const QString
& source
)
1314 QMap
<QString
, QString
> regionalTempInfo
;
1316 if (d
->m_weatherData
[source
].normalHigh
.isEmpty()) {
1317 regionalTempInfo
.insert("normalHigh", "N/A");
1320 regionalTempInfo
.insert("normalHigh", d
->m_weatherData
[source
].normalHigh
);
1322 regionalTempInfo
.insert("normalHigh", QString("%1").arg(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].normalHigh
.toFloat())));
1326 if (d
->m_weatherData
[source
].normalLow
.isEmpty()) {
1327 regionalTempInfo
.insert("normalLow", "N/A");
1330 regionalTempInfo
.insert("normalLow", d
->m_weatherData
[source
].normalLow
);
1332 regionalTempInfo
.insert("normalLow", QString("%1").arg(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].normalLow
.toFloat())));
1337 regionalTempInfo
.insert("regionalTempUnit", QString("%1C").arg(QChar(176)));
1339 regionalTempInfo
.insert("regionalTempUnit", QString("%1F").arg(QChar(176)));
1342 return regionalTempInfo
;
1345 QMap
<QString
, QString
> EnvCanadaIon::yesterdayWeather(const QString
& source
)
1347 QMap
<QString
, QString
> yesterdayInfo
;
1349 if (d
->m_weatherData
[source
].prevHigh
.isEmpty()) {
1350 yesterdayInfo
.insert("prevHigh", "N/A");
1353 yesterdayInfo
.insert("prevHigh", d
->m_weatherData
[source
].prevHigh
);
1355 yesterdayInfo
.insert("prevHigh", QString::number(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].prevHigh
.toFloat())));
1359 if (d
->m_weatherData
[source
].prevLow
.isEmpty()) {
1360 yesterdayInfo
.insert("prevLow", "N/A");
1363 yesterdayInfo
.insert("prevLow", d
->m_weatherData
[source
].prevLow
);
1365 yesterdayInfo
.insert("prevLow", QString::number(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].prevLow
.toFloat()), 'f', 1));
1370 yesterdayInfo
.insert("yesterdayTempUnit", QString("%1C").arg(QChar(176)));
1372 yesterdayInfo
.insert("yesterdayTempUnit", QString("%1F").arg(QChar(176)));
1375 if (d
->m_weatherData
[source
].prevPrecipTotal
== "Trace") {
1376 yesterdayInfo
.insert("prevPrecip", "Trace");
1377 return yesterdayInfo
;
1380 if (d
->m_weatherData
[source
].prevPrecipTotal
.isEmpty()) {
1381 yesterdayInfo
.insert("prevPrecip", "N/A");
1384 yesterdayInfo
.insert("prevPrecipTotal", d
->m_weatherData
[source
].prevPrecipTotal
);
1385 yesterdayInfo
.insert("prevPrecipUnit", d
->m_weatherData
[source
].prevPrecipType
);
1387 yesterdayInfo
.insert("prevPrecipTotal", QString::number(WeatherFormula::millimetersToIN(d
->m_weatherData
[source
].prevPrecipTotal
.toFloat()), 'f', 1));
1388 yesterdayInfo
.insert("prevPrecipUnit", QString("in"));
1392 return yesterdayInfo
;
1395 QMap
<QString
, QString
> EnvCanadaIon::sunriseSet(const QString
& source
)
1397 QMap
<QString
, QString
> sunInfo
;
1399 if (d
->m_weatherData
[source
].sunriseTimestamp
.isEmpty()) {
1400 sunInfo
.insert("sunrise", "N/A");
1402 sunInfo
.insert("sunrise", d
->m_weatherData
[source
].sunriseTimestamp
);
1405 if (d
->m_weatherData
[source
].sunsetTimestamp
.isEmpty()) {
1406 sunInfo
.insert("sunset", "N/A");
1408 sunInfo
.insert("sunset", d
->m_weatherData
[source
].sunsetTimestamp
);
1414 QMap
<QString
, QString
> EnvCanadaIon::moonriseSet(const QString
& source
)
1416 QMap
<QString
, QString
> moonInfo
;
1418 if (d
->m_weatherData
[source
].moonriseTimestamp
.isEmpty()) {
1419 moonInfo
.insert("moonrise", "N/A");
1421 moonInfo
.insert("moonrise", d
->m_weatherData
[source
].moonriseTimestamp
);
1424 if (d
->m_weatherData
[source
].moonsetTimestamp
.isEmpty()) {
1425 moonInfo
.insert("moonset", "N/A");
1427 moonInfo
.insert("moonset", d
->m_weatherData
[source
].moonsetTimestamp
);
1433 QMap
<QString
, QString
> EnvCanadaIon::weatherRecords(const QString
& source
)
1435 QMap
<QString
, QString
> recordInfo
;
1437 if (d
->m_weatherData
[source
].recordHigh
== 0) {
1438 recordInfo
.insert("recordHigh", "N/A");
1441 recordInfo
.insert("recordHigh", QString("%1").arg(d
->m_weatherData
[source
].recordHigh
));
1443 recordInfo
.insert("recordHigh", QString::number(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].recordHigh
), 'f', 1));
1447 if (d
->m_weatherData
[source
].recordLow
== 0) {
1448 recordInfo
.insert("recordLow", "N/A");
1451 recordInfo
.insert("recordLow", QString("%1").arg(d
->m_weatherData
[source
].recordLow
));
1453 recordInfo
.insert("recordLow", QString::number(WeatherFormula::celsiusToF(d
->m_weatherData
[source
].recordLow
), 'f', 1));
1459 recordInfo
.insert("recordTempUnit", QString("%1C").arg(QChar(176)));
1461 recordInfo
.insert("recordTempUnit", QString("%1F").arg(QChar(176)));
1464 if (d
->m_weatherData
[source
].recordRain
== 0) {
1465 recordInfo
.insert("recordRain", "N/A");
1468 recordInfo
.insert("recordRain", QString("%1").arg(d
->m_weatherData
[source
].recordRain
));
1469 recordInfo
.insert("recordRainUnit", QString("mm"));
1471 recordInfo
.insert("recordRain", QString::number(WeatherFormula::millimetersToIN(d
->m_weatherData
[source
].recordRain
), 'f', 1));
1472 recordInfo
.insert("recordRainUnit", QString("in"));
1476 if (d
->m_weatherData
[source
].recordSnow
== 0) {
1477 recordInfo
.insert("recordSnow", "N/A");
1480 recordInfo
.insert("recordSnow", QString("%1").arg(d
->m_weatherData
[source
].recordSnow
));
1481 recordInfo
.insert("recordSnowUnit", QString("cm"));
1483 recordInfo
.insert("recordSnow", QString::number(WeatherFormula::centimetersToIN(d
->m_weatherData
[source
].recordSnow
), 'f', 1));
1484 recordInfo
.insert("recordSnowUnit", QString("in"));
1491 #include "ion_envcan.moc"