File indexing completed on 2025-01-12 05:01:50
0001 /* 0002 SPDX-FileCopyrightText: 2007-2009, 2019 Shawn Starr <shawn.starr@rogers.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /* Ion for Environment Canada XML data */ 0008 0009 #pragma once 0010 0011 #include "../ion.h" 0012 0013 #include <Plasma5Support/DataEngineConsumer> 0014 0015 #include <QDateTime> 0016 #include <QXmlStreamReader> 0017 0018 class KJob; 0019 namespace KIO 0020 { 0021 class Job; 0022 } // namespace KIO 0023 0024 class WeatherData 0025 { 0026 public: 0027 WeatherData(); 0028 0029 // WeatherEvent can have more than one, especially in Canada, eh? :) 0030 struct WeatherEvent { 0031 QString url; 0032 int priority; 0033 QString description; 0034 QString timestamp; 0035 }; 0036 0037 // Five day forecast 0038 struct ForecastInfo { 0039 ForecastInfo(); 0040 0041 QString forecastPeriod; 0042 QString forecastSummary; 0043 QString iconName; 0044 QString shortForecast; 0045 0046 float tempHigh; 0047 float tempLow; 0048 float popPrecent; 0049 QString windForecast; 0050 0051 QString precipForecast; 0052 QString precipType; 0053 QString precipTotalExpected; 0054 int forecastHumidity; 0055 }; 0056 0057 QString creditUrl; 0058 QString countryName; 0059 QString longTerritoryName; 0060 QString shortTerritoryName; 0061 QString cityName; 0062 QString regionName; 0063 QString stationID; 0064 double stationLatitude; 0065 double stationLongitude; 0066 0067 // Current observation information. 0068 QString obsTimestamp; 0069 QDateTime observationDateTime; 0070 0071 QString condition; 0072 float temperature; 0073 float dewpoint; 0074 0075 // In winter windchill, in summer, humidex 0076 QString humidex; 0077 float windchill; 0078 0079 float pressure; 0080 QString pressureTendency; 0081 0082 float visibility; 0083 float humidity; 0084 0085 float windSpeed; 0086 float windGust; 0087 QString windDirection; 0088 QString windDegrees; 0089 0090 QList<WeatherData::WeatherEvent *> warnings; 0091 0092 float normalHigh; 0093 float normalLow; 0094 0095 QString forecastTimestamp; 0096 0097 QString UVIndex; 0098 QString UVRating; 0099 0100 // 5 day Forecast 0101 QList<WeatherData::ForecastInfo *> forecasts; 0102 0103 // Historical data from previous day. 0104 float prevHigh; 0105 float prevLow; 0106 QString prevPrecipType; 0107 QString prevPrecipTotal; 0108 0109 // Almanac info 0110 QString sunriseTimestamp; 0111 QString sunsetTimestamp; 0112 QString moonriseTimestamp; 0113 QString moonsetTimestamp; 0114 0115 // Historical Records 0116 float recordHigh; 0117 float recordLow; 0118 float recordRain; 0119 float recordSnow; 0120 0121 QString solarDataTimeEngineSourceName; 0122 bool isNight = false; 0123 }; 0124 0125 Q_DECLARE_TYPEINFO(WeatherData::WeatherEvent, Q_RELOCATABLE_TYPE); 0126 Q_DECLARE_TYPEINFO(WeatherData::ForecastInfo, Q_RELOCATABLE_TYPE); 0127 Q_DECLARE_TYPEINFO(WeatherData, Q_RELOCATABLE_TYPE); 0128 0129 /** 0130 * https://weather.gc.ca/mainmenu/disclaimer_e.html 0131 */ 0132 class Q_DECL_EXPORT EnvCanadaIon : public IonInterface, public Plasma5Support::DataEngineConsumer 0133 { 0134 Q_OBJECT 0135 0136 public: 0137 EnvCanadaIon(QObject *parent); 0138 ~EnvCanadaIon() override; 0139 0140 public: // IonInterface API 0141 bool updateIonSource(const QString &source) override; 0142 0143 public Q_SLOTS: 0144 // for solar data pushes from the time engine 0145 void dataUpdated(const QString &sourceName, const Plasma5Support::DataEngine::Data &data); 0146 0147 protected: // IonInterface API 0148 void reset() override; 0149 0150 private Q_SLOTS: 0151 void setup_slotDataArrived(KIO::Job *, const QByteArray &); 0152 void setup_slotJobFinished(KJob *); 0153 0154 void slotDataArrived(KIO::Job *, const QByteArray &); 0155 void slotJobFinished(KJob *); 0156 0157 private: 0158 void updateWeather(const QString &source); 0159 0160 /* Environment Canada Methods - Internal for Ion */ 0161 void deleteForecasts(); 0162 0163 QMap<QString, ConditionIcons> setupConditionIconMappings() const; 0164 QMap<QString, ConditionIcons> setupForecastIconMappings() const; 0165 0166 QMap<QString, ConditionIcons> const &conditionIcons() const; 0167 QMap<QString, ConditionIcons> const &forecastIcons() const; 0168 0169 // Load and Parse the place XML listing 0170 void getXMLSetup(); 0171 bool readXMLSetup(); 0172 0173 // Load and parse the specific place(s) 0174 void getXMLData(const QString &source); 0175 bool readXMLData(const QString &source, QXmlStreamReader &xml); 0176 0177 // Check if place specified is valid or not 0178 QStringList validate(const QString &source) const; 0179 0180 // Catchall for unknown XML tags 0181 void parseUnknownElement(QXmlStreamReader &xml) const; 0182 0183 // Parse weather XML data 0184 void parseWeatherSite(WeatherData &data, QXmlStreamReader &xml); 0185 void parseDateTime(WeatherData &data, QXmlStreamReader &xml, WeatherData::WeatherEvent *event = nullptr); 0186 void parseLocations(WeatherData &data, QXmlStreamReader &xml); 0187 void parseConditions(WeatherData &data, QXmlStreamReader &xml); 0188 void parseWarnings(WeatherData &data, QXmlStreamReader &xml); 0189 void parseWindInfo(WeatherData &data, QXmlStreamReader &xml); 0190 void parseWeatherForecast(WeatherData &data, QXmlStreamReader &xml); 0191 void parseRegionalNormals(WeatherData &data, QXmlStreamReader &xml); 0192 void parseForecast(WeatherData &data, QXmlStreamReader &xml, WeatherData::ForecastInfo *forecast); 0193 void parseShortForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader &xml); 0194 void parseForecastTemperatures(WeatherData::ForecastInfo *forecast, QXmlStreamReader &xml); 0195 void parseWindForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader &xml); 0196 void parsePrecipitationForecast(WeatherData::ForecastInfo *forecast, QXmlStreamReader &xml); 0197 void parsePrecipTotals(WeatherData::ForecastInfo *forecast, QXmlStreamReader &xml); 0198 void parseUVIndex(WeatherData &data, QXmlStreamReader &xml); 0199 void parseYesterdayWeather(WeatherData &data, QXmlStreamReader &xml); 0200 void parseAstronomicals(WeatherData &data, QXmlStreamReader &xml); 0201 void parseWeatherRecords(WeatherData &data, QXmlStreamReader &xml); 0202 0203 void parseFloat(float &value, QXmlStreamReader &xml); 0204 0205 private: 0206 struct XMLMapInfo { 0207 QString cityName; 0208 QString territoryName; 0209 QString cityCode; 0210 }; 0211 0212 // Key dicts 0213 QHash<QString, EnvCanadaIon::XMLMapInfo> m_places; 0214 0215 // Weather information 0216 QHash<QString, WeatherData> m_weatherData; 0217 0218 // Store KIO jobs 0219 QHash<KJob *, QXmlStreamReader *> m_jobXml; 0220 QHash<KJob *, QString> m_jobList; 0221 QStringList m_sourcesToReset; 0222 QXmlStreamReader m_xmlSetup; 0223 0224 bool emitWhenSetup; 0225 };