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{
20QString KWeatherCorePrivate::toFixedString(double num)
21{
22 std::ostringstream oss;
23 oss << std::fixed << std::setprecision(2) << num;
24 return QString::fromStdString(oss.str());
25}
26
27QDir KWeatherCorePrivate::getCacheDirectory(double latitude, double longitude)
28{
29#ifdef Q_OS_ANDROID
30 QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/cache/") + toFixedString(latitude) + QStringLiteral("/")
31 + toFixedString(longitude));
32 if (!dir.exists())
33 dir.mkpath(QStringLiteral("."));
34 return dir;
35#else
36 QDir dir(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/kweather/cache/") + toFixedString(latitude)
37 + QStringLiteral("/") + toFixedString(longitude));
38 if (!dir.exists()) {
39 dir.mkpath(QStringLiteral("."));
40 }
41 return dir;
42#endif
43}
44
45// rank weather (for what best describes the day overall)
46// only need neutral icons
47// ### needs to be alphabetically sorted by icon name!
48struct {
49 const char *iconName;
50 int rank;
51} static constexpr const WEATHER_ICON_PRIORITY_RANK[] = {
52 {"weather-clear", 0},
53 {"weather-clouds", 2},
54 {"weather-few-clouds", 1},
55 {"weather-fog", 3},
56 {"weather-freezing-rain", 6},
57 {"weather-freezing-scattered-rain", 6},
58 {"weather-freezing-scattered-rain-storm", 7},
59 {"weather-freezing-storm", 6},
60 {"weather-hail", 5},
61 {"weather-mist", 3},
62 {"weather-none-available", -1},
63 {"weather-showers", 5},
64 {"weather-showers-scattered", 4},
65 {"weather-showers-scattered-storm", 7},
66 {"weather-snow", 5},
67 {"weather-snow-rain", 6},
68 {"weather-snow-scattered", 4},
69 {"weather-snow-scattered-storm", 7},
70 {"weather-snow-storm", 7},
71 {"weather-storm", 7},
72};
73
74int KWeatherCorePrivate::weatherIconPriorityRank(const QString &icon)
75{
76 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) {
77 return QLatin1String(lhs.iconName) < rhs;
78 });
79 if (it != std::end(WEATHER_ICON_PRIORITY_RANK) && QLatin1String((*it).iconName) == icon) {
80 return (*it).rank;
81 }
82
83 return 0;
84}
85
86// https://api.met.no/weatherapi/weathericon/2.0/legends
87// ### needs to be alphabetically sorted by key!
88struct {
89 const char *key;
90 const char *icon;
91 const KLazyLocalizedString desc;
92} static constexpr const WEATHER_API_DESC_MAP[] = {
93 {"clearsky_day", "weather-clear", kli18n("Clear")},
94 {"clearsky_neutral", "weather-clear", kli18n("Clear")},
95 {"clearsky_night", "weather-clear-night", kli18n("Clear")},
96 {"cloudy_day", "weather-clouds", kli18n("Cloudy")},
97 {"cloudy_neutral", "weather-clouds", kli18n("Cloudy")},
98 {"cloudy_night", "weather-clouds-night", kli18n("Cloudy")},
99 {"fair_day", "weather-few-clouds", kli18n("Partly Sunny")},
100 {"fair_neutral", "weather-few-clouds", kli18n("Light Clouds")},
101 {"fair_night", "weather-few-clouds-night", kli18n("Light Clouds")},
102 {"fog_day", "weather-fog", kli18n("Fog")},
103 {"fog_neutral", "weather-fog", kli18n("Fog")},
104 {"fog_night", "weather-fog", kli18n("Fog")},
105
106 {"heavyrain_day", "weather-showers-day", kli18n("Heavy Rain")},
107 {"heavyrain_neutral", "weather-showers", kli18n("Heavy Rain")},
108 {"heavyrain_night", "weather-showers-night", kli18n("Heavy Rain")},
109 {"heavyrainandthunder_day", "weather-storm-day", kli18n("Thunderstorm with Heavy Rain")},
110 {"heavyrainandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Heavy Rain")},
111 {"heavyrainandthunder_night", "weather-storm-night", kli18n("Thunderstorm with Heavy Rain")},
112 {"heavyrainshowers_day", "weather-showers-day", kli18n("Heavy Rain Shower")},
113 {"heavyrainshowers_neutral", "weather-showers", kli18n("Heavy Rain Shower")},
114 {"heavyrainshowers_night", "weather-showers-night", kli18n("Heavy Rain Shower")},
115 {"heavyrainshowersandthunder_day", "weather-storm-day", kli18n("Thunderstorm with Heavy Rain Shower")},
116 {"heavyrainshowersandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Heavy Rain Shower")},
117 {"heavyrainshowersandthunder_night", "weather-storm-night", kli18n("Thunderstorm with Heavy Rain Shower")},
118
119 {"heavysleet_day", "weather-freezing-rain", kli18n("Heavy Sleet")},
120 {"heavysleet_neutral", "weather-freezing-rain", kli18n("Heavy Sleet")},
121 {"heavysleet_night", "weather-freezing-rain", kli18n("Heavy Sleet")},
122 {"heavysleetandthunder_day", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet")},
123 {"heavysleetandthunder_neutral", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet")},
124 {"heavysleetandthunder_night", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet")},
125 {"heavysleetshowers_day", "weather-freezing-rain-day", kli18n("Heavy Sleet Shower")},
126 {"heavysleetshowers_neutral", "weather-freezing-rain", kli18n("Heavy Sleet Shower")},
127 {"heavysleetshowers_night", "weather-freezing-rain-night", kli18n("Heavy Sleet Shower")},
128 {"heavysleetshowersandthunder_day", "weather-freezing-storm-day", kli18n("Thunderstorm with Heavy Sleet Shower")},
129 {"heavysleetshowersandthunder_neutral", "weather-freezing-storm", kli18n("Thunderstorm with Heavy Sleet Shower")},
130 {"heavysleetshowersandthunder_night", "weather-freezing-storm-night", kli18n("Thunderstorm with Heavy Sleet Shower")},
131
132 {"heavysnow_day", "weather-snow", kli18n("Heavy Snow")},
133 {"heavysnow_neutral", "weather-snow", kli18n("Heavy Snow")},
134 {"heavysnow_night", "weather-snow", kli18n("Heavy Snow")},
135 {"heavysnowshowers_day", "weather-snow-day", kli18n("Heavy Snow Shower")},
136 {"heavysnowshowers_neutral", "weather-snow", kli18n("Heavy Snow Shower")},
137 {"heavysnowshowers_night", "weather-snow-night", kli18n("Heavy Snow Shower")},
138 {"heavysnowshowersandthunder_day", "weather-snow-storm-day", kli18n("Thunderstorm with Heavy Snow Shower")},
139 {"heavysnowshowersandthunder_neutral", "weather-snow-storm", kli18n("Thunderstorm with Heavy Snow Shower")},
140 {"heavysnowshowersandthunder_night", "weather-snow-storm-night", kli18n("Thunderstorm with Heavy Snow Shower")},
141
142 {"lightrain_day", "weather-showers-scattered", kli18n("Light Rain")},
143 {"lightrain_neutral", "weather-showers-scattered", kli18n("Light Rain")},
144 {"lightrain_night", "weather-showers-scattered", kli18n("Light Rain")},
145 {"lightrainandthunder_day", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain")},
146 {"lightrainandthunder_neutral", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain")},
147 {"lightrainandthunder_night", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain")},
148 {"lightrainshowers_day", "weather-showers-scattered-day", kli18n("Light Rain Shower")},
149 {"lightrainshowers_neutral", "weather-showers-scattered", kli18n("Light Rain Shower")},
150 {"lightrainshowers_night", "weather-showers-scattered-night", kli18n("Light Rain Shower")},
151 {"lightrainshowersandthunder_day", "weather-showers-scattered-storm-day", kli18n("Thunderstorm with Light Rain Shower")},
152 {"lightrainshowersandthunder_neutral", "weather-showers-scattered-storm", kli18n("Thunderstorm with Light Rain Shower")},
153 {"lightrainshowersandthunder_night", "weather-showers-scattered-storm-night", kli18n("Thunderstorm with Light Rain Shower")},
154
155 {"lightsleet_day", "weather-showers-scattered", kli18n("Light Sleet")},
156 {"lightsleet_neutral", "weather-showers-scattered", kli18n("Light Sleet")},
157 {"lightsleet_night", "weather-showers-scattered", kli18n("Light Sleet")},
158 {"lightsleetandthunder_day", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet")},
159 {"lightsleetandthunder_neutral", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet")},
160 {"lightsleetandthunder_night", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet")},
161 {"lightsleetshowers_day", "weather-freezing-scattered-rain-day", kli18n("Light Sleet Shower")},
162 {"lightsleetshowers_neutral", "weather-freezing-scattered-rain", kli18n("Light Sleet Shower")},
163 {"lightsleetshowers_night", "weather-freezing-scattered-rain-night", kli18n("Light Sleet Shower")},
164
165 {"lightsnow_day", "weather-snow-scattered", kli18n("Light Snow")},
166 {"lightsnow_neutral", "weather-snow-scattered", kli18n("Light Snow")},
167 {"lightsnow_night", "weather-snow-scattered", kli18n("Light Snow")},
168 {"lightsnowandthunder_day", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow")},
169 {"lightsnowandthunder_neutral", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow")},
170 {"lightsnowandthunder_night", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow")},
171 {"lightsnowshowers_day", "weather-snow-scattered-day", kli18n("Light Snow Shower")},
172 {"lightsnowshowers_neutral", "weather-snow-scattered", kli18n("Light Snow Shower")},
173 {"lightsnowshowers_night", "weather-snow-scattered-night", kli18n("Light Snow Shower")},
174
175 {"lightssleetshowersandthunder_day", "weather-freezing-scattered-rain-storm-day", kli18n("Thunderstorm with Light Sleet Shower")},
176 {"lightssleetshowersandthunder_neutral", "weather-freezing-scattered-rain-storm", kli18n("Thunderstorm with Light Sleet Shower")},
177 {"lightssleetshowersandthunder_night", "weather-freezing-scattered-rain-storm-night", kli18n("Thunderstorm with Light Sleet Shower")},
178 {"lightssnowshowersandthunder_day", "weather-snow-scattered-storm-day", kli18n("Thunderstorm with Light Snow Shower")},
179 {"lightssnowshowersandthunder_neutral", "weather-snow-scattered-storm", kli18n("Thunderstorm with Light Snow Shower")},
180 {"lightssnowshowersandthunder_night", "weather-snow-scattered-storm-night", kli18n("Thunderstorm with Light Snow Shower")},
181
182 {"partlycloudy_day", "weather-clouds", kli18n("Partly Cloudy")},
183 {"partlycloudy_neutral", "weather-clouds", kli18n("Partly Cloudy")},
184 {"partlycloudy_night", "weather-clouds-night", kli18n("Partly Cloudy")},
185
186 {"rain_day", "weather-showers", kli18n("Rain")},
187 {"rain_neutral", "weather-showers", kli18n("Rain")},
188 {"rain_night", "weather-showers", kli18n("Rain")},
189 {"rainandthunder_day", "weather-storm", kli18n("Thunderstorm with Rain")},
190 {"rainandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Rain")},
191 {"rainandthunder_night", "weather-storm", kli18n("Thunderstorm with Rain")},
192 {"rainshowers_day", "weather-showers-day", kli18n("Rain Shower")},
193 {"rainshowers_neutral", "weather-showers", kli18n("Rain Shower")},
194 {"rainshowers_night", "weather-showers-night", kli18n("Rain Shower")},
195 {"rainshowersandthunder_day", "weather-storm-day", kli18n("Thunderstorm with Rain Shower")},
196 {"rainshowersandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Rain Shower")},
197 {"rainshowersandthunder_night", "weather-storm-night", kli18n("Thunderstorm with Rain Shower")},
198
199 {"sleet_day", "weather-freezing-rain", kli18n("Sleet")},
200 {"sleet_neutral", "weather-freezing-rain", kli18n("Sleet")},
201 {"sleet_night", "weather-freezing-rain", kli18n("Sleet")},
202 {"sleetandthunder_day", "weather-storm", kli18n("Thunderstorm with Sleet")},
203 {"sleetandthunder_neutral", "weather-storm", kli18n("Thunderstorm with Sleet")},
204 {"sleetandthunder_night", "weather-storm", kli18n("Thunderstorm with Sleet")},
205 {"sleetshowers_day", "weather-freezing-rain-day", kli18n("Sleet Shower")},
206 {"sleetshowers_neutral", "weather-freezing-rain", kli18n("Sleet Shower")},
207 {"sleetshowers_night", "weather-freezing-rain-night", kli18n("Sleet Shower")},
208 {"sleetshowersandthunder_day", "weather-freezing-storm-day", kli18n("Thunderstorm with Sleet Shower")},
209 {"sleetshowersandthunder_neutral", "weather-freezing-storm", kli18n("Thunderstorm with Sleet Shower")},
210 {"sleetshowersandthunder_night", "weather-freezing-storm-night", kli18n("Thunderstorm with Sleet Shower")},
211
212 {"snow_day", "weather-snow", kli18n("Snow")},
213 {"snow_neutral", "weather-snow", kli18n("Snow")},
214 {"snow_night", "weather-snow", kli18n("Snow")},
215 {"snowandthunder_day", "weather-snow-storm", kli18n("Thunderstorm with Snow")},
216 {"snowandthunder_neutral", "weather-snow-storm", kli18n("Thunderstorm with Snow")},
217 {"snowandthunder_night", "weather-snow-storm", kli18n("Thunderstorm with Snow")},
218 {"snowshowers_day", "weather-snow-day", kli18n("Snow Shower")},
219 {"snowshowers_neutral", "weather-snow", kli18n("Snow Shower")},
220 {"snowshowers_night", "weather-snow-night", kli18n("Snow Shower")},
221 {"snowshowersandthunder_day", "weather-snow-storm-day", kli18n("Thunderstorm with Snow Shower")},
222 {"snowshowersandthunder_neutral", "weather-snow-storm", kli18n("Thunderstorm with Snow Shower")},
223 {"snowshowersandthunder_night", "weather-snow-storm-night", kli18n("Thunderstorm with Snow Shower")},
224
225};
226
227ResolvedWeatherDesc KWeatherCorePrivate::resolveAPIWeatherDesc(const QString &desc)
228{
229 const auto key = desc.toUtf8();
230 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) {
231 return std::strcmp(lhs.key, rhs.constData()) < 0;
232 });
233 if (it != std::end(WEATHER_API_DESC_MAP) && std::strcmp((*it).key, key.constData()) == 0) {
234 return ResolvedWeatherDesc(QLatin1String((*it).icon), (*it).desc.toString());
235 }
236
237 return {};
238}
239
240}
KIOCORE_EXPORT QString dir(const QString &fileClass)
QString writableLocation(StandardLocation type)
QString fromStdString(const std::string &str)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 6 2024 12:12:08 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.