KWeatherCore

kweathercore.cpp
1/*
2 * SPDX-FileCopyrightText: 2020-2021 Han Young <hanyoung@protonmail.com>
3 * SPDX-FileCopyrightText: 2020-2021 Devin Lin <espidev@gmail.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "kweathercore_p.h"
9
10#include <KLazyLocalizedString>
11
12#include <QStandardPaths>
13
14#include <cstring>
15#include <iomanip>
16#include <sstream>
17
18namespace KWeatherCore
19{
20CAPPolygon KWeatherCorePrivate::stringToPolygon(const QString &str)
21{
22 CAPPolygon res;
23#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
24 const auto pairList = QStringView(str).split(QLatin1Char(' '), Qt::SkipEmptyParts);
25#else
26 const auto pairList = str.splitRef(QLatin1Char(' '), Qt::SkipEmptyParts);
27#endif
28
29 res.reserve(pairList.size());
30 for (auto &pair : pairList) {
31 auto coordinate = pair.split(QLatin1Char(','));
32 if (coordinate.size() != 2) {
33 continue;
34 }
35 bool latOk = false, lonOk = false;
36 res.push_back({coordinate.front().toFloat(&latOk), coordinate.back().toFloat(&lonOk)});
37 if (!latOk || !lonOk) {
38 res.pop_back();
39 }
40 }
41 return res;
42}
43
44QString KWeatherCorePrivate::toFixedString(double num)
45{
46 std::ostringstream oss;
47 oss << std::fixed << std::setprecision(2) << num;
48 return QString::fromStdString(oss.str());
49}
50
51QDir KWeatherCorePrivate::getCacheDirectory(double latitude, double longitude)
52{
53#ifdef Q_OS_ANDROID
54 QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/cache/") + toFixedString(latitude) + QStringLiteral("/")
55 + toFixedString(longitude));
56 if (!dir.exists())
57 dir.mkpath(QStringLiteral("."));
58 return dir;
59#else
60 QDir dir(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/kweather/cache/") + toFixedString(latitude)
61 + QStringLiteral("/") + toFixedString(longitude));
62 if (!dir.exists()) {
63 dir.mkpath(QStringLiteral("."));
64 }
65 return dir;
66#endif
67}
68
69CAPAlertInfo::Urgency KWeatherCorePrivate::urgencyStringToEnum(const QString &str)
70{
71 if (str == QLatin1String("Immediate")) {
72 return CAPAlertInfo::Urgency::Immediate;
73 } else if (str == QLatin1String("Expected")) {
74 return CAPAlertInfo::Urgency::Expected;
75 } else if (str == QLatin1String("Future")) {
76 return CAPAlertInfo::Urgency::Future;
77 } else if (str == QLatin1String("Past")) {
78 return CAPAlertInfo::Urgency::Past;
79 } else {
80 return CAPAlertInfo::Urgency::UnknownUrgency;
81 }
82}
83
84CAPAlertInfo::Severity KWeatherCorePrivate::severityStringToEnum(const QString &str)
85{
86 if (str == QLatin1String("Extreme")) {
87 return CAPAlertInfo::Severity::Extreme;
88 } else if (str == QLatin1String("Severe")) {
89 return CAPAlertInfo::Severity::Severe;
90 } else if (str == QLatin1String("Moderate")) {
91 return CAPAlertInfo::Severity::Moderate;
92 } else if (str == QLatin1String("Minor")) {
93 return CAPAlertInfo::Severity::Minor;
94 } else {
95 return CAPAlertInfo::Severity::UnknownSeverity;
96 }
97}
98
99CAPAlertInfo::Certainty KWeatherCorePrivate::certaintyStringToEnum(const QString &str)
100{
101 if (str == QLatin1String("Observed")) {
102 return CAPAlertInfo::Certainty::Observed;
103 } else if (str == QLatin1String("Likely")) {
104 return CAPAlertInfo::Certainty::Likely;
105 } else if (str == QLatin1String("Possible")) {
106 return CAPAlertInfo::Certainty::Possible;
107 } else if (str == QLatin1String("Unlikely")) {
108 return CAPAlertInfo::Certainty::Unlikely;
109 } else {
110 return CAPAlertInfo::Certainty::UnknownCertainty;
111 }
112}
113
114// rank weather (for what best describes the day overall)
115// only need neutral icons
116// ### needs to be alphabetically sorted by icon name!
117struct {
118 const char *iconName;
119 int rank;
120} static constexpr const WEATHER_ICON_PRIORITY_RANK[] = {
121 {"weather-clear", 0},
122 {"weather-clouds", 2},
123 {"weather-few-clouds", 1},
124 {"weather-fog", 3},
125 {"weather-freezing-rain", 6},
126 {"weather-freezing-scattered-rain", 6},
127 {"weather-freezing-scattered-rain-storm", 7},
128 {"weather-freezing-storm", 6},
129 {"weather-hail", 5},
130 {"weather-mist", 3},
131 {"weather-none-available", -1},
132 {"weather-showers", 5},
133 {"weather-showers-scattered", 4},
134 {"weather-showers-scattered-storm", 7},
135 {"weather-snow", 5},
136 {"weather-snow-rain", 6},
137 {"weather-snow-scattered", 4},
138 {"weather-snow-scattered-storm", 7},
139 {"weather-snow-storm", 7},
140 {"weather-storm", 7},
141};
142
143int KWeatherCorePrivate::weatherIconPriorityRank(const QString &icon)
144{
145 const auto it = std::lower_bound(std::begin(WEATHER_ICON_PRIORITY_RANK), std::end(WEATHER_ICON_PRIORITY_RANK), icon, [](const auto &lhs, const auto &rhs) {
146 return QLatin1String(lhs.iconName) < rhs;
147 });
148 if (it != std::end(WEATHER_ICON_PRIORITY_RANK) && QLatin1String((*it).iconName) == icon) {
149 return (*it).rank;
150 }
151
152 return 0;
153}
154
155// https://api.met.no/weatherapi/weathericon/2.0/legends
156// ### needs to be alphabetically sorted by key!
157struct {
158 const char *key;
159 const char *icon;
160 const KLazyLocalizedString desc;
161} static constexpr const WEATHER_API_DESC_MAP[] = {
162 {"clearsky_day", "weather-clear", kli18n("Clear")},
163 {"clearsky_neutral", "weather-clear", kli18n("Clear")},
164 {"clearsky_night", "weather-clear-night", kli18n("Clear")},
165 {"cloudy_day", "weather-clouds", kli18n("Cloudy")},
166 {"cloudy_neutral", "weather-clouds", kli18n("Cloudy")},
167 {"cloudy_night", "weather-clouds-night", kli18n("Cloudy")},
168 {"fair_day", "weather-few-clouds", kli18n("Partly Sunny")},
169 {"fair_neutral", "weather-few-clouds", kli18n("Light Clouds")},
170 {"fair_night", "weather-few-clouds-night", kli18n("Light Clouds")},
171 {"fog_day", "weather-fog", kli18n("Fog")},
172 {"fog_neutral", "weather-fog", kli18n("Fog")},
173 {"fog_night", "weather-fog", kli18n("Fog")},
174
175 {"heavyrain_day", "weather-showers-day", kli18n("Heavy Rain")},
176 {"heavyrain_neutral", "weather-showers", kli18n("Heavy Rain")},
177 {"heavyrain_night", "weather-showers-night", kli18n("Heavy Rain")},
178 {"heavyrainandthunder_day", "weather-storm-day", kli18n("Thunderstorm with Heavy Rain")},
179 {"heavyrainandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Heavy Rain")},
180 {"heavyrainandthunder_night", "weather-storm-night", kli18n("Thunderstorm with Heavy Rain")},
181 {"heavyrainshowers_day", "weather-showers-day", kli18n("Heavy Rain Shower")},
182 {"heavyrainshowers_neutral", "weather-showers", kli18n("Heavy Rain Shower")},
183 {"heavyrainshowers_night", "weather-showers-night", kli18n("Heavy Rain Shower")},
184 {"heavyrainshowersandthunder_day", "weather-storm-day", kli18n("Thunderstorm with Heavy Rain Shower")},
185 {"heavyrainshowersandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Heavy Rain Shower")},
186 {"heavyrainshowersandthunder_night", "weather-storm-night", kli18n("Thunderstorm with Heavy Rain Shower")},
187
188 {"heavysleet_day", "weather-freezing-rain", kli18n("Heavy Sleet")},
189 {"heavysleet_neutral", "weather-freezing-rain", kli18n("Heavy Sleet")},
190 {"heavysleet_night", "weather-freezing-rain", kli18n("Heavy Sleet")},
191 {"heavysleetandthunder_day", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet")},
192 {"heavysleetandthunder_neutral", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet")},
193 {"heavysleetandthunder_night", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet")},
194 {"heavysleetshowers_day", "weather-freezing-rain-day", kli18n("Heavy Sleet Shower")},
195 {"heavysleetshowers_neutral", "weather-freezing-rain", kli18n("Heavy Sleet Shower")},
196 {"heavysleetshowers_night", "weather-freezing-rain-night", kli18n("Heavy Sleet Shower")},
197 {"heavysleetshowersandthunder_day", "weather-freezing-storm-day", kli18n("Thunderstorm with Heavy Sleet Shower")},
198 {"heavysleetshowersandthunder_neutral", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet Shower")},
199 {"heavysleetshowersandthunder_night", "weather-freezing-storm-night", kli18n("Thunderstorm with Heavy Sleet Shower")},
200
201 {"heavysnow_day", "weather-snow", kli18n("Heavy Snow")},
202 {"heavysnow_neutral", "weather-snow", kli18n("Heavy Snow")},
203 {"heavysnow_night", "weather-snow", kli18n("Heavy Snow")},
204 {"heavysnowshowers_day", "weather-snow-day", kli18n("Heavy Snow Shower")},
205 {"heavysnowshowers_neutral", "weather-snow", kli18n("Heavy Snow Shower")},
206 {"heavysnowshowers_night", "weather-snow-night", kli18n("Heavy Snow Shower")},
207 {"heavysnowshowersandthunder_day", "weather-snow-storm-day", kli18n("Thunderstorm with Heavy Snow Shower")},
208 {"heavysnowshowersandthunder_neutral", "weather-snow-storm", kli18n("Thunderstorm with Heavy Snow Shower")},
209 {"heavysnowshowersandthunder_night", "weather-snow-storm-night", kli18n("Thunderstorm with Heavy Snow Shower")},
210
211 {"lightrain_day", "weather-showers-scattered", kli18n("Light Rain")},
212 {"lightrain_neutral", "weather-showers-scattered", kli18n("Light Rain")},
213 {"lightrain_night", "weather-showers-scattered", kli18n("Light Rain")},
214 {"lightrainandthunder_day", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain")},
215 {"lightrainandthunder_neutral", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain")},
216 {"lightrainandthunder_night", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain")},
217 {"lightrainshowers_day", "weather-showers-scattered-day", kli18n("Light Rain Shower")},
218 {"lightrainshowers_neutral", "weather-showers-scattered", kli18n("Light Rain Shower")},
219 {"lightrainshowers_night", "weather-showers-scattered-night", kli18n("Light Rain Shower")},
220 {"lightrainshowersandthunder_day", "weather-showers-scattered-storm-day", kli18n("Thunderstorm with Light Rain Shower")},
221 {"lightrainshowersandthunder_neutral", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain Shower")},
222 {"lightrainshowersandthunder_night", "weather-showers-scattered-storm-night", kli18n("Thunderstorm with Light Rain Shower")},
223
224 {"lightsleet_day", "weather-showers-scattered", kli18n("Light Sleet")},
225 {"lightsleet_neutral", "weather-showers-scattered", kli18n("Light Sleet")},
226 {"lightsleet_night", "weather-showers-scattered", kli18n("Light Sleet")},
227 {"lightsleetandthunder_day", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet")},
228 {"lightsleetandthunder_neutral", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet")},
229 {"lightsleetandthunder_night", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet")},
230 {"lightsleetshowers_day", "weather-freezing-scattered-rain-day", kli18n("Light Sleet Shower")},
231 {"lightsleetshowers_neutral", "weather-freezing-scattered-rain", kli18n("Light Sleet Shower")},
232 {"lightsleetshowers_night", "weather-freezing-scattered-rain-night", kli18n("Light Sleet Shower")},
233
234 {"lightsnow_day", "weather-snow-scattered", kli18n("Light Snow")},
235 {"lightsnow_neutral", "weather-snow-scattered", kli18n("Light Snow")},
236 {"lightsnow_night", "weather-snow-scattered", kli18n("Light Snow")},
237 {"lightsnowandthunder_day", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow")},
238 {"lightsnowandthunder_neutral", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow")},
239 {"lightsnowandthunder_night", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow")},
240 {"lightsnowshowers_day", "weather-snow-scattered-day", kli18n("Light Snow Shower")},
241 {"lightsnowshowers_neutral", "weather-snow-scattered", kli18n("Light Snow Shower")},
242 {"lightsnowshowers_night", "weather-snow-scattered-night", kli18n("Light Snow Shower")},
243
244 {"lightssleetshowersandthunder_day", "weather-freezing-scattered-rain-storm-day", kli18n("Thunderstorm with Light Sleet Shower")},
245 {"lightssleetshowersandthunder_neutral", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet Shower")},
246 {"lightssleetshowersandthunder_night", "weather-freezing-scattered-rain-storm-night", kli18n("Thunderstorm with Light Sleet Shower")},
247 {"lightssnowshowersandthunder_day", "weather-snow-scattered-storm-day", kli18n("Thunderstorm with Light Snow Shower")},
248 {"lightssnowshowersandthunder_neutral", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow Shower")},
249 {"lightssnowshowersandthunder_night", "weather-snow-scattered-storm-night", kli18n("Thunderstorm with Light Snow Shower")},
250
251 {"partlycloudy_day", "weather-clouds", kli18n("Partly Cloudy")},
252 {"partlycloudy_neutral", "weather-clouds", kli18n("Partly Cloudy")},
253 {"partlycloudy_night", "weather-clouds-night", kli18n("Partly Cloudy")},
254
255 {"rain_day", "weather-showers", kli18n("Rain")},
256 {"rain_neutral", "weather-showers", kli18n("Rain")},
257 {"rain_night", "weather-showers", kli18n("Rain")},
258 {"rainandthunder_day", "weather-storm", kli18n("Thunderstorm with Rain")},
259 {"rainandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Rain")},
260 {"rainandthunder_night", "weather-storm", kli18n("Thunderstorm with Rain")},
261 {"rainshowers_day", "weather-showers-day", kli18n("Rain Shower")},
262 {"rainshowers_neutral", "weather-showers", kli18n("Rain Shower")},
263 {"rainshowers_night", "weather-showers-night", kli18n("Rain Shower")},
264 {"rainshowersandthunder_day", "weather-storm-day", kli18n("Thunderstorm with Rain Shower")},
265 {"rainshowersandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Rain Shower")},
266 {"rainshowersandthunder_night", "weather-storm-night", kli18n("Thunderstorm with Rain Shower")},
267
268 {"sleet_day", "weather-freezing-rain", kli18n("Sleet")},
269 {"sleet_neutral", "weather-freezing-rain", kli18n("Sleet")},
270 {"sleet_night", "weather-freezing-rain", kli18n("Sleet")},
271 {"sleetandthunder_day", "weather-storm", kli18n("Thunderstorm with Sleet")},
272 {"sleetandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Sleet")},
273 {"sleetandthunder_night", "weather-storm", kli18n("Thunderstorm with Sleet")},
274 {"sleetshowers_day", "weather-freezing-rain-day", kli18n("Sleet Shower")},
275 {"sleetshowers_neutral", "weather-freezing-rain", kli18n("Sleet Shower")},
276 {"sleetshowers_night", "weather-freezing-rain-night", kli18n("Sleet Shower")},
277 {"sleetshowersandthunder_day", "weather-freezing-storm-day", kli18n("Thunderstorm with Sleet Shower")},
278 {"sleetshowersandthunder_neutral", "weather-freezing-storm", kli18n("Thunderstorm with Sleet Shower")},
279 {"sleetshowersandthunder_night", "weather-freezing-storm-night", kli18n("Thunderstorm with Sleet Shower")},
280
281 {"snow_day", "weather-snow", kli18n("Snow")},
282 {"snow_neutral", "weather-snow", kli18n("Snow")},
283 {"snow_night", "weather-snow", kli18n("Snow")},
284 {"snowandthunder_day", "weather-snow-storm", kli18n("Thunderstorm with Snow")},
285 {"snowandthunder_neutral", "weather-snow-storm", kli18n("Thunderstorm with Snow")},
286 {"snowandthunder_night", "weather-snow-storm", kli18n("Thunderstorm with Snow")},
287 {"snowshowers_day", "weather-snow-day", kli18n("Snow Shower")},
288 {"snowshowers_neutral", "weather-snow", kli18n("Snow Shower")},
289 {"snowshowers_night", "weather-snow-night", kli18n("Snow Shower")},
290 {"snowshowersandthunder_day", "weather-snow-storm-day", kli18n("Thunderstorm with Snow Shower")},
291 {"snowshowersandthunder_neutral", "weather-snow-storm", kli18n("Thunderstorm with Snow Shower")},
292 {"snowshowersandthunder_night", "weather-snow-storm-night", kli18n("Thunderstorm with Snow Shower")},
293
294};
295
296ResolvedWeatherDesc KWeatherCorePrivate::resolveAPIWeatherDesc(const QString &desc)
297{
298 const auto key = desc.toUtf8();
299 const auto it = std::lower_bound(std::begin(WEATHER_API_DESC_MAP), std::end(WEATHER_API_DESC_MAP), key, [](const auto &lhs, const auto &rhs) {
300 return std::strcmp(lhs.key, rhs.constData()) < 0;
301 });
302 if (it != std::end(WEATHER_API_DESC_MAP) && std::strcmp((*it).key, key.constData()) == 0) {
303 return ResolvedWeatherDesc(QLatin1String((*it).icon), (*it).desc.toString());
304 }
305
306 return {};
307}
308
309}
KIOCORE_EXPORT QString dir(const QString &fileClass)
QString writableLocation(StandardLocation type)
QString fromStdString(const std::string &str)
void reserve(qsizetype size)
QList< QStringView > split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
SkipEmptyParts
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 24 2024 12:02:06 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.