From 0e7033dd09c78eed673bfcde768483f6ad925ff7 Mon Sep 17 00:00:00 2001 From: Mavridis Philippe Date: Sat, 13 Nov 2021 14:17:53 +0200 Subject: [PATCH] KWeather: updated icon handling. The newly added class abstracts away icon names from the main code and has the ability to fall back to "safer" icon choices so as to ensure (if possible) icon theme consistency. Signed-off-by: Mavridis Philippe --- kweather/CMakeLists.txt | 4 +- kweather/metar_parser.cpp | 86 ++++++++++--------- kweather/metar_parser.h | 2 +- kweather/weather_icon.cpp | 171 ++++++++++++++++++++++++++++++++++++++ kweather/weather_icon.h | 20 +++++ kweather/weatherlib.cpp | 3 +- 6 files changed, 245 insertions(+), 41 deletions(-) create mode 100644 kweather/weather_icon.cpp create mode 100644 kweather/weather_icon.h diff --git a/kweather/CMakeLists.txt b/kweather/CMakeLists.txt index dcf4722..b618585 100644 --- a/kweather/CMakeLists.txt +++ b/kweather/CMakeLists.txt @@ -36,7 +36,7 @@ tde_add_tdeinit_executable( kweatherreport AUTOMOC ##### kweatherservice (executable) ############## tde_add_executable( kweatherservice AUTOMOC - SOURCES main.cpp metar_parser.cpp + SOURCES main.cpp weather_icon.cpp metar_parser.cpp weatherlib.cpp weatherservice.cpp weatherservice.skel stationdatabase.cpp sun.cpp weatherservice.stub @@ -92,7 +92,7 @@ add_custom_command( # # tde_add_executable( metar_parser_test AUTOMOC # SOURCES metar_parser_test.cpp metar_parser.cpp -# stationdatabase.cpp sun.cpp +# weather_icon.cpp stationdatabase.cpp sun.cpp # ) # # add_test( NAME metar_parser_test-test diff --git a/kweather/metar_parser.cpp b/kweather/metar_parser.cpp index 44e2c73..c7baa62 100644 --- a/kweather/metar_parser.cpp +++ b/kweather/metar_parser.cpp @@ -28,6 +28,7 @@ email : jratke@comcast.net #include "metar_parser.h" #include "stationdatabase.h" +#include "weather_icon.h" #include "sun.h" // Temperature conversion macros @@ -257,7 +258,7 @@ bool MetarParser::parseCurrent(const TQString &s) if (sCode.contains("DZ")) { phenomena = i18n("Drizzle"); - weatherInfo.theWeather = "light_rain"; + weatherInfo.theWeather = iconName( WeatherIcon::LightRain, false ); } else if (sCode.contains("RA")) { @@ -272,32 +273,32 @@ bool MetarParser::parseCurrent(const TQString &s) else if (sCode.contains("SG")) { phenomena = i18n("Snow Grains"); - weatherInfo.theWeather = "snow4"; + weatherInfo.theWeather = iconName( WeatherIcon::Snow, false, 4 ); } else if (sCode.contains("IC")) { phenomena = i18n("Ice Crystals"); - weatherInfo.theWeather = "hail"; + weatherInfo.theWeather = iconName( WeatherIcon::Hail, false ); } else if (sCode.contains("PE")) { phenomena = i18n("Ice Pellets"); - weatherInfo.theWeather = "hail"; + weatherInfo.theWeather = iconName( WeatherIcon::Hail, false ); } else if (s.contains("GR")) { phenomena = i18n("Hail"); - weatherInfo.theWeather = "hail"; + weatherInfo.theWeather = iconName( WeatherIcon::Hail, false ); } else if (sCode.contains("GS")) { phenomena = i18n("Small Hail Pellets"); - weatherInfo.theWeather = "hail"; + weatherInfo.theWeather = iconName( WeatherIcon::Hail, false ); } else if (s.contains("UP")) { phenomena = i18n("Unknown Precipitation"); - weatherInfo.theWeather = iconName("shower1"); + weatherInfo.theWeather = iconName( WeatherIcon::Showers, isNight(weatherInfo.reportLocation), 1); } else if (sCode.contains("BR")) { @@ -721,24 +722,25 @@ bool MetarParser::parseStationNeedsMaintenance(const TQString &s) void MetarParser::calcCurrentIcon() { - // Default to overcast clouds - if ( weatherInfo.clouds == -1 ) - weatherInfo.clouds = 64; + bool night = isNight( weatherInfo.reportLocation ); if (weatherInfo.theWeather.isEmpty()) { + if (weatherInfo.clouds == 0) - weatherInfo.theWeather = iconName("sunny"); + weatherInfo.theWeather = iconName( WeatherIcon::Sunny, night ); else if (weatherInfo.clouds > 0 && weatherInfo.clouds <= 2) - weatherInfo.theWeather = iconName("cloudy1"); + weatherInfo.theWeather = iconName( WeatherIcon::Cloudy, night, 1 ); else if ( weatherInfo.clouds > 2 && weatherInfo.clouds <= 4) - weatherInfo.theWeather = iconName("cloudy2"); + weatherInfo.theWeather = iconName( WeatherIcon::Cloudy, night, 2 ); else if ( weatherInfo.clouds > 4 && weatherInfo.clouds <= 8) - weatherInfo.theWeather = iconName("cloudy3"); + weatherInfo.theWeather = iconName( WeatherIcon::Cloudy, night, 3 ); else if ( weatherInfo.clouds > 8 && weatherInfo.clouds < 63) - weatherInfo.theWeather = iconName( "cloudy4" ); + weatherInfo.theWeather = iconName( WeatherIcon::Cloudy, night, 4 ); + else if (weatherInfo.clouds < 0) + weatherInfo.theWeather = iconName( WeatherIcon::Cloudy, night, weatherInfo.clouds); else - weatherInfo.theWeather = "cloudy5"; + weatherInfo.theWeather = iconName( WeatherIcon::Cloudy, night, 5 ); } else if (weatherInfo.theWeather == "tstorm") { @@ -746,11 +748,11 @@ void MetarParser::calcCurrentIcon() weatherInfo.clouds = 30; if (weatherInfo.clouds >= 0 && weatherInfo.clouds <= 10) - weatherInfo.theWeather = iconName("tstorm1"); + weatherInfo.theWeather = iconName( WeatherIcon::Thunderstorm, night, 1 ); else if ( weatherInfo.clouds > 10 && weatherInfo.clouds <= 20) - weatherInfo.theWeather = iconName("tstorm2"); + weatherInfo.theWeather = iconName( WeatherIcon::Thunderstorm, night, 2 ); else - weatherInfo.theWeather = "tstorm3"; + weatherInfo.theWeather = iconName( WeatherIcon::Thunderstorm, night, 3 ); } else if (weatherInfo.theWeather == "shower") { @@ -758,11 +760,11 @@ void MetarParser::calcCurrentIcon() weatherInfo.clouds = 30; if (weatherInfo.clouds >= 0 && weatherInfo.clouds <= 10) - weatherInfo.theWeather = iconName("shower1"); + weatherInfo.theWeather = iconName( WeatherIcon::Showers, night, 1 ); else if ( weatherInfo.clouds > 10 && weatherInfo.clouds <= 20) - weatherInfo.theWeather = iconName("shower2"); + weatherInfo.theWeather = iconName( WeatherIcon::Showers, night, 2 ); else - weatherInfo.theWeather = "shower3"; + weatherInfo.theWeather = iconName( WeatherIcon::Showers, night, 3 ); } else if (weatherInfo.theWeather == "snow") { @@ -770,22 +772,22 @@ void MetarParser::calcCurrentIcon() weatherInfo.clouds = 30; if (weatherInfo.clouds >= 0 && weatherInfo.clouds <= 8) - weatherInfo.theWeather = iconName("snow1"); + weatherInfo.theWeather = iconName( WeatherIcon::Snow, night, 1 ); else if ( weatherInfo.clouds > 8 && weatherInfo.clouds <= 16) - weatherInfo.theWeather = iconName("snow2"); + weatherInfo.theWeather = iconName( WeatherIcon::Snow, night, 2 ); else if (weatherInfo.clouds > 16 && weatherInfo.clouds <= 24) - weatherInfo.theWeather = iconName("snow3"); + weatherInfo.theWeather = iconName( WeatherIcon::Snow, night, 3 ); else - weatherInfo.theWeather = "snow5"; + weatherInfo.theWeather = iconName( WeatherIcon::Snow, night, 5 ); } - else if (isNight(weatherInfo.reportLocation) && weatherInfo.theWeather == "mist") - weatherInfo.theWeather = "mist_night"; - else if (isNight(weatherInfo.reportLocation) && weatherInfo.theWeather == "fog") - weatherInfo.theWeather = "fog_night"; else if ( weatherInfo.theWeather == "mist" || weatherInfo.theWeather == "fog" ) { if ( weatherInfo.clouds >= 63 ) - weatherInfo.theWeather = "cloudy5"; + weatherInfo.theWeather = iconName( WeatherIcon::Cloudy, night, 5 ); + else if ( weatherInfo.theWeather == "mist" ) + weatherInfo.theWeather = iconName( WeatherIcon::Mist, night ); + else if ( weatherInfo.theWeather == "fog" ) + weatherInfo.theWeather = iconName( WeatherIcon::Fog, night ); } kdDebug(12006) << "Clouds: " << weatherInfo.clouds << ", Icon: " @@ -861,13 +863,23 @@ bool MetarParser::isNight(const TQString &stationID) const } } -TQString MetarParser::iconName( const TQString &icon ) const +TQString MetarParser::iconName( int condition, bool night, int strength ) const { - TQString _iconName = icon; - - if ( isNight( weatherInfo.reportLocation ) ) - _iconName += "_night"; - + TQString _iconName; + if( strength != 0 ) + { + // Simple + WeatherIcon* wi = new WeatherIcon( condition, night, strength ); + _iconName = wi->name(); + delete wi; + } + else + { + // Ranged + WeatherIcon* wi = new WeatherIcon( condition, night ); + _iconName = wi->name(); + delete wi; + } return _iconName; } diff --git a/kweather/metar_parser.h b/kweather/metar_parser.h index 772fe11..a5ab028 100644 --- a/kweather/metar_parser.h +++ b/kweather/metar_parser.h @@ -92,7 +92,7 @@ class MetarParser void calcCurrentIcon(); void calcWindChill(); bool isNight(const TQString &stationID) const; - TQString iconName( const TQString &icon ) const; + TQString iconName( int condition, bool night, int strength = 0 ) const; /* * Reset the internal WeatherInfo struct of the class so that diff --git a/kweather/weather_icon.cpp b/kweather/weather_icon.cpp new file mode 100644 index 0000000..3c61213 --- /dev/null +++ b/kweather/weather_icon.cpp @@ -0,0 +1,171 @@ +#include + +#include "weather_icon.h" + +WeatherIcon::WeatherIcon( int condition, bool night ) + : iconLoader() +{ + TQString name; + + switch( condition ) + { + + case Sunny: + { + name = "weather-clear"; + iconName = ( night ? name.append("-night") : name ); + return; + } + + case Fog: + { + name = "weather-fog"; + if( night && iconExists( TQString(name.latin1()).append("-night")) ) + { + name.append("-night"); + } + iconName = name; + return; + } + + case Mist: + { + name = "weather-mist"; + if( night && iconExists( TQString(name.latin1()).append("-night")) ) + { + name.append("-night"); + } + iconName = name; + return; + } + + case Overcast: { iconName = "weather-overcast"; return; } + case Hail: { iconName = "weather-freezing-rain"; return; } + case LightRain: { iconName = "weather-showers-scattered"; return; } + case Sleet: { iconName = "weather-snow-rain"; return; } + } +} + +WeatherIcon::WeatherIcon( int condition, bool night, unsigned int strength ) + : iconLoader() +{ + TQString name; + + switch ( condition ) + { + case Cloudy: + { + switch ( strength ) + { + case 1: { name = "weather-few-clouds"; break; } + + case 2: + { + name = "weather-moderate-clouds"; + if (! iconExists(name) ) + { + name = "weather-few-clouds"; + } + break; + } + + case 3: { name = "weather-clouds"; break; } + + case 4: + { + name = "weather-ample-clouds"; + if (! iconExists(name) ) + { + name = "weather-clouds"; + } + break; + } + + case 5: { iconName = "weather-many-clouds"; return; } + default: { iconName = "weather-clouds"; return; } + } + + iconName = name.append( night ? "-night" : "" ); + return; + } + + case Showers: + { + switch ( strength ) + { + case 1: { name = "weather-showers-scattered"; break; } + case 2: { name = "weather-showers"; break; } + case 3: + default: { iconName = "weather-showers"; return; } + } + + iconName = name.append( night ? "-night" : "-day" ); + return; + } + + case Snow: + { + switch( strength ) + { + case 1: { name = "weather-snow-scattered"; break; } + case 2: + { + name = "weather-snow-moderate"; + if (! iconExists( TQString(name.latin1()).append("-day")) ) + { + name = "weather-snow-scattered"; + } + break; + } + case 3: + { + name = "weather-snow-ample"; + if ( iconExists( TQString(name.latin1()).append("-day") ) ) + break; + } + case 4: { iconName = "weather-snow-scattered"; return; } + case 5: + default: { iconName = "weather-snow"; return; } + } + + iconName = name.append( night ? "-night" : "-day" ); + return; + } + + case Thunderstorm: + switch ( strength ) + { + case 1: { name = "weather-storm"; break; } + case 2: + { + name = "weather-storm-moderate"; + if (! iconExists( TQString(name.latin1()).append("-day")) ) + { + name = "weather-storm"; + } + break; + } + case 3: + default: { iconName = "weather-storm"; return; } + } + + iconName = name.append( night ? "-night" : "-day" ); + return; + } +} + +WeatherIcon::~WeatherIcon() +{} + + +bool WeatherIcon::iconExists( TQString& icon, bool inTheme ) +{ + if ( inTheme ) + { + return iconLoader->theme()->iconPath(icon, TDEIcon::SizeMedium, TDEIcon::MatchExact).isValid(); + } + else + { + return !(iconLoader->iconPath(icon, TDEIcon::SizeMedium, true).isNull()); + } +} diff --git a/kweather/weather_icon.h b/kweather/weather_icon.h new file mode 100644 index 0000000..732e266 --- /dev/null +++ b/kweather/weather_icon.h @@ -0,0 +1,20 @@ +class TDEIconLoader; + +class WeatherIcon { + public: + enum SimpleCondition { Sunny, Fog, Mist, Overcast, Hail, LightRain, Sleet }; + enum RangedCondition { Cloudy, Showers, Snow, Thunderstorm }; + + WeatherIcon( int condition /* SimpleCondition */, bool night ); + WeatherIcon( int condition /* RangedCondition */, bool night, unsigned int strength ); + ~WeatherIcon(); + + static TQString unknown() { return "weather-none-available"; }; + TQString& name() { return iconName; } + + private: + bool iconExists( TQString& icon, bool inTheme = true ); + + TDEIconLoader* iconLoader; + TQString iconName = unknown(); +}; diff --git a/kweather/weatherlib.cpp b/kweather/weatherlib.cpp index c628d77..32d653c 100644 --- a/kweather/weatherlib.cpp +++ b/kweather/weatherlib.cpp @@ -39,6 +39,7 @@ email : geiseri@msoe.edu #include "stationdatabase.h" #include "sun.h" #include "weatherlib.h" +#include "weather_icon.h" #include "weatherlib.moc" @@ -271,7 +272,7 @@ TQString WeatherLib::windChill(const TQString &stationID){ TQString WeatherLib::iconName(const TQString &stationID){ - TQString result("dunno"); + TQString result = WeatherIcon::unknown(); // isEmpty is true for null or 0 length strings if ( !stationID.isEmpty() )