File indexing completed on 2024-05-12 15:31:20
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2009 Bastian Holst <bastianholst@gmx.de> 0004 // 0005 0006 // Self 0007 #include "WeatherData.h" 0008 0009 // Marble 0010 #include "MarbleGlobal.h" 0011 #include "MarbleDirs.h" 0012 #include "MarbleDebug.h" 0013 0014 // Qt 0015 #include <QAtomicInt> 0016 #include <QDate> 0017 #include <QDateTime> 0018 #include <QHash> 0019 #include <QLocale> 0020 #include <QImage> 0021 0022 #include <cmath> 0023 0024 namespace Marble 0025 { 0026 0027 // Factors 0028 // m/s to knots 0029 const qreal MPS2KN = 1.9437; 0030 const qreal KN2MPS = 1 / MPS2KN; 0031 // m/s to kilometer per hour 0032 const qreal MPS2KPH = 3.6; 0033 const qreal KPH2MPS = 1 / MPS2KPH; 0034 // m/s to miles per hour 0035 const qreal MPS2MPH = MPS2KPH * KM2MI; 0036 const qreal MPH2MPS = 1 / MPS2MPH; 0037 // HectoPascal to KiloPascal 0038 const qreal HPA2KPA = 10; 0039 const qreal KPA2HPA = 1/HPA2KPA; 0040 // Bar to HectoPascal 0041 const qreal BAR2HPA = 1000; 0042 const qreal HPA2BAR = 1/BAR2HPA; 0043 // mmHg to HectoPascal 0044 const qreal HG2HPA = 1.33; 0045 const qreal HPA2HG = 1/HG2HPA; 0046 // inchHg to HectoPascal 0047 const qreal IHG2HPA = HG2HPA * 25.4; 0048 const qreal HPA2IHG = HPA2HG / 25.4; 0049 0050 // Summands 0051 // Kelvin to degree Celsius 0052 const qreal KEL2CEL = -273.15; 0053 const qreal CEL2KEL = -KEL2CEL; 0054 0055 class WeatherDataPrivate 0056 { 0057 Q_DECLARE_TR_FUNCTIONS ( WeatherDataPrivate ) 0058 0059 public: 0060 WeatherDataPrivate() 0061 : m_pubTime(), 0062 m_dataDate(), 0063 m_condition( WeatherData::ConditionNotAvailable ), 0064 m_windDirection( WeatherData::DirectionNotAvailable ), 0065 m_windSpeed( -1.0 ), 0066 m_temperature( -1.0 ), 0067 m_maxTemperature( -1.0 ), 0068 m_minTemperature( -1.0 ), 0069 m_visibility( WeatherData::VisibilityNotAvailable ), 0070 m_pressure( -1.0 ), 0071 m_pressureDevelopment( WeatherData::PressureDevelopmentNotAvailable ), 0072 m_humidity( -1.0 ), 0073 ref( 1 ) 0074 { 0075 initializeIcons(); 0076 } 0077 0078 WeatherDataPrivate( const WeatherDataPrivate &other ) 0079 : m_pubTime( other.m_pubTime ), 0080 m_dataDate( other.m_dataDate ), 0081 m_condition( other.m_condition ), 0082 m_windDirection( other.m_windDirection ), 0083 m_windSpeed( other.m_windSpeed ), 0084 m_temperature( other.m_temperature ), 0085 m_maxTemperature( other.m_maxTemperature ), 0086 m_minTemperature( other.m_minTemperature ), 0087 m_visibility( other.m_visibility ), 0088 m_pressure( other.m_pressure ), 0089 m_pressureDevelopment( other.m_pressureDevelopment ), 0090 m_humidity( other.m_humidity ), 0091 ref( other.ref ) 0092 { 0093 initializeIcons(); 0094 } 0095 0096 static void initializeIcons() 0097 { 0098 if( s_iconPath.size() == 0 ) { 0099 // Clouds 0100 s_iconPath.insert( WeatherData::ConditionNotAvailable, 0101 MarbleDirs::path(QStringLiteral("weather/weather-none-available.png"))); 0102 s_iconPath.insert( WeatherData::ClearDay, 0103 MarbleDirs::path(QStringLiteral("weather/weather-clear.png"))); 0104 s_iconPath.insert( WeatherData::ClearNight, 0105 MarbleDirs::path(QStringLiteral("weather/weather-clear-night.png"))); 0106 s_iconPath.insert( WeatherData::FewCloudsDay, 0107 MarbleDirs::path(QStringLiteral("weather/weather-few-clouds.png"))); 0108 s_iconPath.insert( WeatherData::FewCloudsNight, 0109 MarbleDirs::path(QStringLiteral("weather/weather-few-clouds-night.png"))); 0110 s_iconPath.insert( WeatherData::PartlyCloudyDay, 0111 MarbleDirs::path(QStringLiteral("weather/weather-clouds.png"))); 0112 s_iconPath.insert( WeatherData::PartlyCloudyNight, 0113 MarbleDirs::path(QStringLiteral("weather/weather-clouds-night.png"))); 0114 s_iconPath.insert( WeatherData::Overcast, 0115 MarbleDirs::path(QStringLiteral("weather/weather-many-clouds.png"))); 0116 0117 // Rain 0118 s_iconPath.insert( WeatherData::LightShowersDay, 0119 MarbleDirs::path(QStringLiteral("weather/weather-showers-scattered-day.png"))); 0120 s_iconPath.insert( WeatherData::LightShowersNight, 0121 MarbleDirs::path(QStringLiteral("weather/weather-showers-scattered-night.png"))); 0122 s_iconPath.insert( WeatherData::ShowersDay, 0123 MarbleDirs::path(QStringLiteral("weather/weather-showers-day.png"))); 0124 s_iconPath.insert( WeatherData::ShowersNight, 0125 MarbleDirs::path(QStringLiteral("weather/weather-showers-night.png"))); 0126 s_iconPath.insert( WeatherData::LightRain, 0127 MarbleDirs::path(QStringLiteral("weather/weather-showers-scattered.png"))); 0128 s_iconPath.insert( WeatherData::Rain, 0129 MarbleDirs::path(QStringLiteral("weather/weather-showers.png"))); 0130 0131 // Special 0132 s_iconPath.insert( WeatherData::ChanceThunderstormDay, 0133 MarbleDirs::path(QStringLiteral("weather/weather-storm-day.png"))); 0134 s_iconPath.insert( WeatherData::ChanceThunderstormNight, 0135 MarbleDirs::path(QStringLiteral("weather/weather-storm-night.png"))); 0136 s_iconPath.insert( WeatherData::Thunderstorm, 0137 MarbleDirs::path(QStringLiteral("weather/weather-storm.png"))); 0138 s_iconPath.insert( WeatherData::Hail, 0139 MarbleDirs::path(QStringLiteral("weather/weather-hail.png"))); 0140 s_iconPath.insert( WeatherData::ChanceSnowDay, 0141 MarbleDirs::path(QStringLiteral("weather/weather-snow-scattered-day.png"))); 0142 s_iconPath.insert( WeatherData::ChanceSnowNight, 0143 MarbleDirs::path(QStringLiteral("weather/weather-snow-scattered-night.png"))); 0144 s_iconPath.insert( WeatherData::LightSnow, 0145 MarbleDirs::path(QStringLiteral("weather/weather-snow-scattered.png"))); 0146 s_iconPath.insert( WeatherData::Snow, 0147 MarbleDirs::path(QStringLiteral("weather/weather-snow.png"))); 0148 s_iconPath.insert( WeatherData::RainSnow, 0149 MarbleDirs::path(QStringLiteral("weather/weather-snow-rain.png"))); 0150 s_iconPath.insert( WeatherData::Mist, 0151 MarbleDirs::path(QStringLiteral("weather/weather-mist.png"))); 0152 s_iconPath.insert( WeatherData::SandStorm, 0153 MarbleDirs::path(QStringLiteral("weather/weather-none-available.png"))); 0154 } 0155 } 0156 0157 static qreal fromKelvin( qreal temp, WeatherData::TemperatureUnit format ) 0158 { 0159 if( WeatherData::Kelvin == format ) { 0160 return temp; 0161 } 0162 else if ( WeatherData::Celsius == format ) { 0163 return temp + KEL2CEL; 0164 } 0165 else if ( WeatherData::Fahrenheit == format ) { 0166 return ( temp * 1.8 ) - 459.67; 0167 } 0168 else { 0169 mDebug() << "Wrong temperature format"; 0170 return 0; 0171 } 0172 } 0173 0174 static qreal toKelvin( qreal temp, WeatherData::TemperatureUnit format ) 0175 { 0176 if( WeatherData::Kelvin == format ) { 0177 return temp; 0178 } 0179 else if ( WeatherData::Celsius == format ) { 0180 return temp + CEL2KEL; 0181 } 0182 else if ( WeatherData::Fahrenheit == format ) { 0183 return ( temp + 459.67 ) / 1.8; 0184 } 0185 else { 0186 mDebug() << "Wrong temperature format"; 0187 return 0; 0188 } 0189 } 0190 0191 static bool isPositiveValue( qreal value ) 0192 { 0193 // A small tolerance 0194 return value > -0.5; 0195 } 0196 0197 static QString generateTemperatureString( qreal temp, WeatherData::TemperatureUnit format ) 0198 { 0199 QLocale locale = QLocale::system(); 0200 // We round to integer. 0201 QString string = locale.toString( floor( fromKelvin( temp, format ) + 0.5 ) ); 0202 switch ( format ) { 0203 case WeatherData::Kelvin: 0204 string += QLatin1String(" K"); 0205 break; 0206 case WeatherData::Celsius: 0207 string += QString::fromUtf8("°C"); 0208 break; 0209 case WeatherData::Fahrenheit: 0210 string += QString::fromUtf8("°F"); 0211 break; 0212 } 0213 return string; 0214 } 0215 0216 0217 WeatherDataPrivate& operator=( const WeatherDataPrivate &other ) 0218 { 0219 m_pubTime = other.m_pubTime; 0220 m_dataDate = other.m_dataDate; 0221 m_condition = other.m_condition; 0222 m_windDirection = other.m_windDirection; 0223 m_windSpeed = other.m_windSpeed; 0224 m_temperature = other.m_temperature; 0225 m_maxTemperature = other.m_maxTemperature; 0226 m_minTemperature = other.m_minTemperature; 0227 m_visibility = other.m_visibility; 0228 m_pressure = other.m_pressure; 0229 m_pressureDevelopment = other.m_pressureDevelopment; 0230 m_humidity = other.m_humidity; 0231 0232 ref = other.ref; 0233 return *this; 0234 } 0235 0236 QDateTime m_pubTime; 0237 QDate m_dataDate; 0238 WeatherData::WeatherCondition m_condition; 0239 WeatherData::WindDirection m_windDirection; 0240 0241 // Wind speed stored in m/s 0242 qreal m_windSpeed; 0243 0244 // Temperatures stored in Kelvin 0245 qreal m_temperature; 0246 qreal m_maxTemperature; 0247 qreal m_minTemperature; 0248 0249 WeatherData::Visibility m_visibility; 0250 0251 // Pressure stored in hecto pascal 0252 qreal m_pressure; 0253 0254 WeatherData::PressureDevelopment m_pressureDevelopment; 0255 0256 // Relative humidity 0257 qreal m_humidity; 0258 0259 QAtomicInt ref; 0260 0261 static QHash<WeatherData::WeatherCondition, QImage> s_icons; 0262 static QHash<WeatherData::WeatherCondition, QString> s_iconPath; 0263 static WeatherData::TemperatureUnit s_standardTemperatureUnit; 0264 }; 0265 0266 QHash<WeatherData::WeatherCondition, QImage> WeatherDataPrivate::s_icons = QHash<WeatherData::WeatherCondition, QImage>(); 0267 QHash<WeatherData::WeatherCondition, QString> WeatherDataPrivate::s_iconPath = QHash<WeatherData::WeatherCondition, QString>(); 0268 WeatherData::TemperatureUnit WeatherDataPrivate::s_standardTemperatureUnit = WeatherData::Celsius; 0269 0270 WeatherData::WeatherData() 0271 : d( new WeatherDataPrivate() ) 0272 { 0273 } 0274 0275 WeatherData::WeatherData( const WeatherData &other ) 0276 : d( other.d ) 0277 { 0278 d->ref.ref(); 0279 } 0280 0281 WeatherData::~WeatherData() 0282 { 0283 if ( !d->ref.deref() ) 0284 delete d; 0285 } 0286 0287 bool WeatherData::isValid() const 0288 { 0289 return hasValidPublishingTime() 0290 || hasValidDataDate() 0291 || hasValidCondition() 0292 || hasValidWindDirection() 0293 || hasValidWindSpeed() 0294 || hasValidTemperature() 0295 || hasValidMaxTemperature() 0296 || hasValidMinTemperature() 0297 || hasValidVisibility() 0298 || hasValidPressure() 0299 || hasValidPressureDevelopment() 0300 || hasValidHumidity(); 0301 } 0302 0303 QDateTime WeatherData::publishingTime() const 0304 { 0305 return d->m_pubTime; 0306 } 0307 0308 void WeatherData::setPublishingTime( const QDateTime& dateTime ) 0309 { 0310 detach(); 0311 d->m_pubTime = dateTime.toUTC(); 0312 } 0313 0314 bool WeatherData::hasValidPublishingTime() const 0315 { 0316 return d->m_pubTime.isValid(); 0317 } 0318 0319 QDate WeatherData::dataDate() const 0320 { 0321 return d->m_dataDate; 0322 } 0323 0324 void WeatherData::setDataDate( const QDate& date ) 0325 { 0326 detach(); 0327 d->m_dataDate = date; 0328 } 0329 0330 bool WeatherData::hasValidDataDate() const 0331 { 0332 return d->m_dataDate.isValid(); 0333 } 0334 0335 WeatherData::WeatherCondition WeatherData::condition() const 0336 { 0337 return d->m_condition; 0338 } 0339 0340 void WeatherData::setCondition( WeatherData::WeatherCondition condition ) 0341 { 0342 detach(); 0343 d->m_condition = condition; 0344 } 0345 0346 bool WeatherData::hasValidCondition() const 0347 { 0348 return d->m_condition != WeatherData::ConditionNotAvailable; 0349 } 0350 0351 QString WeatherData::conditionString() const 0352 { 0353 switch ( condition() ) { 0354 case ClearDay: 0355 return tr( "sunny" ); 0356 case ClearNight: 0357 return tr( "clear" ); 0358 case FewCloudsDay: 0359 case FewCloudsNight: 0360 return tr( "few clouds" ); 0361 case PartlyCloudyDay: 0362 case PartlyCloudyNight: 0363 return tr( "partly cloudy" ); 0364 case Overcast: 0365 return tr( "overcast" ); 0366 case LightShowersDay: 0367 case LightShowersNight: 0368 return tr( "light showers" ); 0369 case ShowersDay: 0370 case ShowersNight: 0371 return tr( "showers" ); 0372 case LightRain: 0373 return tr( "light rain" ); 0374 case Rain: 0375 return tr( "rain" ); 0376 case ChanceThunderstormDay: 0377 case ChanceThunderstormNight: 0378 return tr( "occasionally thunderstorm" ); 0379 case Thunderstorm: 0380 return tr( "thunderstorm" ); 0381 case Hail: 0382 return tr( "hail" ); 0383 case ChanceSnowDay: 0384 case ChanceSnowNight: 0385 return tr( "occasionally snow" ); 0386 case LightSnow: 0387 return tr( "light snow" ); 0388 case Snow: 0389 return tr( "snow" ); 0390 case RainSnow: 0391 return tr( "rain and snow" ); 0392 case Mist: 0393 return tr( "mist" ); 0394 case SandStorm: 0395 return tr( "sandstorm" ); 0396 default: 0397 return "Condition not available"; 0398 } 0399 } 0400 0401 QImage WeatherData::icon() const 0402 { 0403 QImage icon = WeatherDataPrivate::s_icons.value( condition() ); 0404 0405 // If the icon is in the hash, simply return it. 0406 if ( !icon.isNull() ) { 0407 return icon; 0408 } 0409 // If it isn't in the hash, the icon will be created (from the value stored in s_iconPath). 0410 else { 0411 icon = QImage( WeatherDataPrivate::s_iconPath.value( condition() ) ); 0412 WeatherDataPrivate::s_icons.insert( condition(), icon ); 0413 return icon; 0414 } 0415 } 0416 0417 QString WeatherData::iconSource() const 0418 { 0419 QString const invalid = MarbleDirs::path(QStringLiteral("weather/weather-none-available.png")); 0420 QString const icon = WeatherDataPrivate::s_iconPath.value( condition() ); 0421 return icon == invalid ? "" : icon; 0422 } 0423 0424 WeatherData::WindDirection WeatherData::windDirection() const 0425 { 0426 return d->m_windDirection; 0427 } 0428 0429 void WeatherData::setWindDirection( WeatherData::WindDirection direction ) 0430 { 0431 detach(); 0432 d->m_windDirection = direction; 0433 } 0434 0435 bool WeatherData::hasValidWindDirection() const 0436 { 0437 return d->m_windDirection != WeatherData::DirectionNotAvailable; 0438 } 0439 0440 QString WeatherData::windDirectionString() const 0441 { 0442 switch ( windDirection() ) { 0443 case N: 0444 return tr( "N" ); 0445 case NNE: 0446 return tr( "NNE" ); 0447 case NE: 0448 return tr( "NE" ); 0449 case ENE: 0450 return tr( "ENE" ); 0451 case E: 0452 return tr( "E" ); 0453 case SSE: 0454 return tr( "SSE" ); 0455 case SE: 0456 return tr( "SE" ); 0457 case ESE: 0458 return tr( "ESE" ); 0459 case S: 0460 return tr( "S" ); 0461 case NNW: 0462 return tr( "NNW" ); 0463 case NW: 0464 return tr( "NW" ); 0465 case WNW: 0466 return tr( "WNW" ); 0467 case W: 0468 return tr( "W" ); 0469 case SSW: 0470 return tr( "SSW" ); 0471 case SW: 0472 return tr( "SW" ); 0473 case WSW: 0474 return tr( "WSW" ); 0475 default: 0476 return ""; 0477 } 0478 } 0479 0480 qreal WeatherData::windSpeed( WeatherData::SpeedUnit format ) const 0481 { 0482 if ( WeatherData::mps == format ) { 0483 return d->m_windSpeed; 0484 } 0485 if ( WeatherData::kph == format ) { 0486 return d->m_windSpeed * MPS2KPH; 0487 } 0488 else if ( WeatherData::mph == format ) { 0489 return d->m_windSpeed * MPS2MPH; 0490 } 0491 else if ( WeatherData::knots == format ) { 0492 return d->m_windSpeed * MPS2KN; 0493 } 0494 else if ( WeatherData::beaufort == format ) { 0495 if( d->m_windSpeed < 0.3 ) 0496 return 0; 0497 else if( d->m_windSpeed < 1.6 ) 0498 return 1; 0499 else if( d->m_windSpeed < 3.4 ) 0500 return 2; 0501 else if( d->m_windSpeed < 5.5 ) 0502 return 3; 0503 else if( d->m_windSpeed < 8.0 ) 0504 return 4; 0505 else if( d->m_windSpeed < 10.8 ) 0506 return 5; 0507 else if( d->m_windSpeed < 13.9 ) 0508 return 6; 0509 else if( d->m_windSpeed < 17.2 ) 0510 return 7; 0511 else if( d->m_windSpeed < 20.8 ) 0512 return 8; 0513 else if( d->m_windSpeed < 24.5 ) 0514 return 9; 0515 else if( d->m_windSpeed < 28.5 ) 0516 return 10; 0517 else if( d->m_windSpeed < 32.7 ) 0518 return 11; 0519 else 0520 return 12; 0521 } 0522 else { 0523 mDebug() << "Wrong speed format"; 0524 return 0; 0525 } 0526 } 0527 0528 void WeatherData::setWindSpeed( qreal speed, WeatherData::SpeedUnit format ) 0529 { 0530 detach(); 0531 if ( WeatherData::mps == format ) { 0532 d->m_windSpeed = speed; 0533 } 0534 if ( WeatherData::kph == format ) { 0535 d->m_windSpeed = speed * KPH2MPS; 0536 } 0537 else if ( WeatherData::mph == format ) { 0538 d->m_windSpeed = speed * MPH2MPS; 0539 } 0540 else if ( WeatherData::knots == format ) { 0541 d->m_windSpeed = speed * KN2MPS; 0542 } 0543 else if ( WeatherData::beaufort == format ) { 0544 int rounded = (int) speed; 0545 if( 0 == rounded ) 0546 d->m_windSpeed = 0.15; 0547 else if( 1 == rounded ) 0548 d->m_windSpeed = 0.95; 0549 else if( 2 == rounded ) 0550 d->m_windSpeed = 2.5; 0551 else if( 3 == rounded ) 0552 d->m_windSpeed = 4.45; 0553 else if( 4 == rounded ) 0554 d->m_windSpeed = 6.75; 0555 else if( 5 == rounded ) 0556 d->m_windSpeed = 9.4; 0557 else if( 6 == rounded ) 0558 d->m_windSpeed = 12.35; 0559 else if( 7 == rounded ) 0560 d->m_windSpeed = 15.55; 0561 else if( 8 == rounded ) 0562 d->m_windSpeed = 19.0; 0563 else if( 9 == rounded ) 0564 d->m_windSpeed = 22.65; 0565 else if( 10 == rounded ) 0566 d->m_windSpeed = 26.5; 0567 else if( 11 == rounded ) 0568 d->m_windSpeed = 30.6; 0569 else 0570 d->m_windSpeed = 34; 0571 } 0572 else { 0573 mDebug() << "Wrong speed format"; 0574 } 0575 } 0576 0577 bool WeatherData::hasValidWindSpeed() const 0578 { 0579 return d->isPositiveValue( d->m_windSpeed ); 0580 } 0581 0582 QString WeatherData::windSpeedString( WeatherData::SpeedUnit unit ) const 0583 { 0584 QLocale locale = QLocale::system(); 0585 // We round to integer. 0586 QString string = locale.toString( floor( windSpeed( unit ) + 0.5 ) ); 0587 string += QLatin1Char(' '); 0588 switch ( unit ) { 0589 case WeatherData::kph: 0590 string += QObject::tr("km/h"); 0591 break; 0592 case WeatherData::mph: 0593 string += QObject::tr("mph"); 0594 break; 0595 case WeatherData::mps: 0596 string += QObject::tr( "m/s" ); 0597 break; 0598 case WeatherData::knots: 0599 string += QObject::tr( "knots" ); 0600 break; 0601 case WeatherData::beaufort: 0602 string += QObject::tr( "Beaufort" ); 0603 break; 0604 } 0605 return string; 0606 } 0607 0608 qreal WeatherData::temperature( WeatherData::TemperatureUnit format ) const 0609 { 0610 return d->fromKelvin( d->m_temperature, format ); 0611 } 0612 0613 void WeatherData::setTemperature( qreal temp, WeatherData::TemperatureUnit format ) 0614 { 0615 detach(); 0616 d->m_temperature = d->toKelvin( temp, format ); 0617 } 0618 0619 bool WeatherData::hasValidTemperature() const 0620 { 0621 return d->isPositiveValue( d->m_temperature ); 0622 } 0623 0624 QString WeatherData::temperatureString( WeatherData::TemperatureUnit format ) const 0625 { 0626 return d->generateTemperatureString( d->m_temperature, 0627 format ); 0628 } 0629 0630 qreal WeatherData::maxTemperature( WeatherData::TemperatureUnit format ) const 0631 { 0632 return d->fromKelvin( d->m_maxTemperature, format ); 0633 } 0634 0635 void WeatherData::setMaxTemperature( qreal temp, WeatherData::TemperatureUnit format ) 0636 { 0637 detach(); 0638 d->m_maxTemperature = d->toKelvin( temp, format ); 0639 } 0640 0641 QString WeatherData::maxTemperatureString( WeatherData::TemperatureUnit format ) const 0642 { 0643 return d->generateTemperatureString( d->m_maxTemperature, 0644 format ); 0645 } 0646 0647 bool WeatherData::hasValidMaxTemperature() const 0648 { 0649 return d->isPositiveValue( d->m_maxTemperature ); 0650 } 0651 0652 qreal WeatherData::minTemperature( WeatherData::TemperatureUnit format ) const 0653 { 0654 return d->fromKelvin( d->m_minTemperature, format ); 0655 } 0656 0657 QString WeatherData::minTemperatureString( WeatherData::TemperatureUnit format ) const 0658 { 0659 return d->generateTemperatureString( d->m_minTemperature, 0660 format ); 0661 } 0662 0663 void WeatherData::setMinTemperature( qreal temp, WeatherData::TemperatureUnit format ) 0664 { 0665 detach(); 0666 d->m_minTemperature = d->toKelvin( temp, format ); 0667 } 0668 0669 bool WeatherData::hasValidMinTemperature() const 0670 { 0671 return d->isPositiveValue( d->m_minTemperature ); 0672 } 0673 0674 WeatherData::Visibility WeatherData::visibility() const 0675 { 0676 return d->m_visibility; 0677 } 0678 0679 void WeatherData::setVisibilty( WeatherData::Visibility visibility ) 0680 { 0681 detach(); 0682 d->m_visibility = visibility; 0683 } 0684 0685 bool WeatherData::hasValidVisibility() const 0686 { 0687 return d->m_visibility != WeatherData::VisibilityNotAvailable; 0688 } 0689 0690 qreal WeatherData::pressure( WeatherData::PressureUnit format ) const 0691 { 0692 if ( WeatherData::HectoPascal == format ) { 0693 return d->m_pressure; 0694 } 0695 else if ( WeatherData::KiloPascal == format ) { 0696 return d->m_pressure * HPA2KPA; 0697 } 0698 else if ( WeatherData::Bar == format ) { 0699 return d->m_pressure * HPA2BAR; 0700 } 0701 else if ( WeatherData::mmHg == format ) { 0702 return d->m_pressure * HPA2HG; 0703 } 0704 else if ( WeatherData::inchHg == format ) { 0705 return d->m_pressure * HPA2IHG; 0706 } 0707 else { 0708 mDebug() << "Wrong pressure format"; 0709 return 0; 0710 } 0711 } 0712 0713 void WeatherData::setPressure( qreal pressure, WeatherData::PressureUnit format ) 0714 { 0715 detach(); 0716 if ( WeatherData::HectoPascal == format ) { 0717 d->m_pressure = pressure; 0718 } 0719 else if ( WeatherData::KiloPascal == format ) { 0720 d->m_pressure = pressure * KPA2HPA; 0721 } 0722 else if ( WeatherData::Bar == format ) { 0723 d->m_pressure = pressure * BAR2HPA; 0724 } 0725 else if ( WeatherData::mmHg == format ) { 0726 d->m_pressure = pressure * HG2HPA; 0727 } 0728 else if ( WeatherData::inchHg == format ) { 0729 d->m_pressure = pressure * IHG2HPA; 0730 } 0731 else { 0732 mDebug() << "Wrong pressure format"; 0733 } 0734 } 0735 0736 bool WeatherData::hasValidPressure() const 0737 { 0738 return d->isPositiveValue( d->m_pressure ); 0739 } 0740 0741 QString WeatherData::pressureString( WeatherData::PressureUnit unit ) const 0742 { 0743 QLocale locale = QLocale::system(); 0744 // We round to integer. 0745 QString string = locale.toString( pressure( unit ), 'f', 2 ); 0746 string += QLatin1Char(' '); 0747 switch ( unit ) { 0748 case WeatherData::HectoPascal: 0749 string += tr( "hPa" ); 0750 break; 0751 case WeatherData::KiloPascal: 0752 string += tr( "kPa" ); 0753 break; 0754 case WeatherData::Bar: 0755 string += tr( "Bar" ); 0756 break; 0757 case WeatherData::mmHg: 0758 string += tr( "mmHg" ); 0759 break; 0760 case WeatherData::inchHg: 0761 string += tr( "inch Hg" ); 0762 break; 0763 } 0764 return string; 0765 } 0766 0767 WeatherData::PressureDevelopment WeatherData::pressureDevelopment() const 0768 { 0769 return d->m_pressureDevelopment; 0770 } 0771 0772 void WeatherData::setPressureDevelopment( WeatherData::PressureDevelopment pressureDevelopment ) 0773 { 0774 detach(); 0775 d->m_pressureDevelopment = pressureDevelopment; 0776 } 0777 0778 bool WeatherData::hasValidPressureDevelopment() const 0779 { 0780 return d->m_pressureDevelopment != WeatherData::PressureDevelopmentNotAvailable; 0781 } 0782 0783 QString WeatherData::pressureDevelopmentString() const 0784 { 0785 switch ( pressureDevelopment() ) { 0786 case Rising: 0787 return tr( "rising", "air pressure is rising" ); 0788 case NoChange: 0789 return tr( "steady", "air pressure has no change" ); 0790 case Falling: 0791 return tr( "falling", "air pressure falls" ); 0792 default: 0793 return ""; 0794 } 0795 } 0796 0797 qreal WeatherData::humidity() const 0798 { 0799 return d->m_humidity; 0800 } 0801 0802 void WeatherData::setHumidity( qreal humidity ) 0803 { 0804 detach(); 0805 d->m_humidity = humidity; 0806 } 0807 0808 bool WeatherData::hasValidHumidity() const 0809 { 0810 return d->isPositiveValue( d->m_humidity ); 0811 } 0812 0813 QString WeatherData::humidityString() const 0814 { 0815 return QString( "%1 %" ).arg( humidity() ); 0816 } 0817 0818 QString WeatherData::toHtml( WeatherData::TemperatureUnit temperatureUnit, 0819 WeatherData::SpeedUnit speedUnit, 0820 WeatherData::PressureUnit pressureUnit ) const 0821 { 0822 QString html; 0823 if ( hasValidPublishingTime() ) { 0824 html += tr( "Publishing time: %1<br>" ) 0825 .arg( publishingTime().toLocalTime().toString() ); 0826 } 0827 if ( hasValidCondition() ) { 0828 html += tr( "Condition: %1<br>" ) 0829 .arg( conditionString() ); 0830 } 0831 if ( hasValidTemperature() ) { 0832 html += tr( "Temperature: %1<br>" ) 0833 .arg( temperatureString( temperatureUnit ) ); 0834 } 0835 if ( hasValidMaxTemperature() ) { 0836 html += tr( "Max temperature: %1<br>" ) 0837 .arg( maxTemperatureString( temperatureUnit ) ); 0838 } 0839 if ( hasValidMinTemperature() ) { 0840 html += tr( "Min temperature: %1<br>" ) 0841 .arg( minTemperatureString( temperatureUnit ) ); 0842 } 0843 if ( hasValidWindDirection() ) { 0844 html += tr( "Wind direction: %1<br>" ) 0845 .arg( windDirectionString() ); 0846 } 0847 if ( hasValidWindSpeed() ) { 0848 html += tr( "Wind speed: %1<br>" ) 0849 .arg( windSpeedString( speedUnit ) ); 0850 } 0851 if ( hasValidPressure() ) { 0852 html += tr( "Pressure: %1<br>" ) 0853 .arg( pressureString( pressureUnit ) ); 0854 } 0855 if ( hasValidPressureDevelopment() ) { 0856 html += tr( "Pressure development: %1<br>") 0857 .arg( pressureDevelopmentString() ); 0858 } 0859 if ( hasValidHumidity() ) { 0860 html += tr( "Humidity: %1<br>" ) 0861 .arg( humidityString() ); 0862 } 0863 0864 return html; 0865 } 0866 0867 WeatherData& WeatherData::operator=( const WeatherData &other ) 0868 { 0869 qAtomicAssign( d, other.d ); 0870 return *this; 0871 } 0872 0873 void WeatherData::detach() 0874 { 0875 qAtomicDetach( d ); 0876 } 0877 0878 } // namespace Marble