Ticket #8356: new-grabber-if.patch

File new-grabber-if.patch, 11.1 KB (added by Alec leamas <gmail: leamas.alec>, 14 years ago)
  • mythweather/weatherScreen.cpp

    Simplify the interface between the grabber and the plugin.
    
    From: Alec Leamas <leamas.alec%AT%gmail.com>
    
    This patch maks the -u <ENG|SI> parameter obsolete. The basic approach is
    that the grabber provides the values it actually gets from the data source
    without making any conversions. If need be, these are done by the plugin.
    
    The purpose is to make a clean division between the grabber which provides
    the data and the plugin which handles the presentation. Eventually, all
    conversions SI<-> ENG now being done in the grabbers can be removed
    together with the handling of the -u parameter. Furhermore. it creates
    a simpler base e. g., when presenting wind speed in either knots, m/s,
    km/h or mph. Since the data is parsed, all formatting is now done by the
    plugin which should make theming and translations easier and more consistent.
    
    Patch is compatible with current grabber interface. It always
    gives the '-u SI' option to the grabber.
    
    A possible  downside is loss of precision in some conversions . Worst case
    is temperatures, where rounding errors possibly gives values 1 degree off.
    This is, BTW, an error present in current grabber code.  To handle this for
    those grabbers which can get a correct ENG or SI value, the patch decodes
    both values in grabber output:
    
    high-0: 12; 35
    
    should be read as 12 degrees Celsius / 35 degrees Fahrenheit. Any part can
    be omitted:
    
    high-0: ;35
    high-0: 12;
    
    in which case plugin makes conversions as necessary. The current 'high-0: 12'
    is handled as today.
    
    With proper changes in the grabbers, the patch removes multiple rounding
    errors in current code and overall reduces the complexity of the interface
    and the grabber.
    ---
    
     mythweather/weatherScreen.cpp |  261 ++++++++++++++++++++++++++++++++++++++---
     mythweather/weatherScreen.h   |    1 
     mythweather/weatherSource.cpp |    2 
     3 files changed, 244 insertions(+), 20 deletions(-)
    
    
    diff --git a/mythweather/weatherScreen.cpp b/mythweather/weatherScreen.cpp
    index a4e7e42..9080e8c 100644
    a b using namespace std; 
    99#include "weather.h"
    1010#include "weatherScreen.h"
    1111
     12static const QString kDegrees         = QString::fromUtf8("°");
     13static const float   MILES_PER_KM     = 0.62137;
     14static const float   IN_HG_PER_MBAR   = 0.02953;
     15
    1216/** Parse and format time according to current locale. */
    1317static QString formatTime(const QString& value)
    1418{
    static QString formatTime(const QString& value) 
    4246    return QString(buff);
    4347}
    4448
     49
     50/** Private class converting grabber values to UI format. */
     51class Converter
     52{
     53    public:
     54        Converter(float factor,
     55                  const QString& metricUnit,
     56                  const QString& engUnit);
     57        virtual QString convert(const QString& value, units_t units);
     58
     59    protected:
     60        virtual float engValue(float value)
     61                           { return m_factor * value; };
     62        virtual float siValue(float value)
     63                           { return value / m_factor; };
     64        virtual QString format(float f)
     65                           { return QString().setNum(f, 'f',  1); };
     66        int round(float f)
     67                { return static_cast<int>(f + (f > 0.0 ? +0.5 : -0.5)); };
     68        virtual QString  parseValues( const QString& input, units_t unit);
     69        QString m_metricUnit;
     70        QString m_engUnit;
     71        float   m_factor;
     72        QString m_value;
     73        QString m_otherValue;
     74
     75};
     76
     77
     78Converter::Converter(float factor,
     79                     const QString& metricUnit,
     80                     const QString& engUnit)
     81{
     82    m_metricUnit = metricUnit;
     83    m_factor = factor;
     84    m_engUnit = engUnit;
     85}
     86
     87
     88class DistanceConverter: public Converter
     89{
     90    public:
     91        DistanceConverter(): Converter( MILES_PER_KM, " km", " mi") {};
     92};
     93
     94
     95class PressureConverter: public Converter
     96{
     97    public:
     98        PressureConverter(): Converter( IN_HG_PER_MBAR, " mb", " in") {};
     99};
     100
     101
     102class VisibilityConverter: public Converter
     103{
     104    public:
     105        VisibilityConverter():Converter( MILES_PER_KM, " km", " mi") {};
     106        QString convert(const QString& value, units_t units);
     107};
     108
     109
     110class TempConverter: public Converter
     111{
     112    public:
     113        TempConverter():
     114                Converter( 0, kDegrees + "C" , kDegrees + "F") {};
     115        float engValue(float f) { return f * 9.0/5.0 + 32; };
     116        float siValue(float f)  { return (f - 32) * 5.0/9.0; };
     117        QString format(float f) {return QString().setNum(f, 'f', 0); };
     118};
     119
     120
     121class PrecipConverter: public Converter
     122{
     123    public:
     124        PrecipConverter(): Converter( 1, " mm" , " mm") {};
     125        QString format( float f) {return QString().setNum(f, 'f', 0); };
     126};
     127
     128
     129class WindConverter: public Converter
     130{
     131    public:
     132        WindConverter(): Converter( MILES_PER_KM, " km/h", " mph") {};
     133};
     134
     135QString Converter::parseValues( const QString& input, units_t units)
     136{
     137    QString siValue = "";
     138    QString engValue = "";
     139
     140    QStringList parts = input.split(";");
     141    if (parts.size() > 2)
     142    {
     143        return QString("NA ( ") + input + ")";
     144    }
     145    else if (parts.size() == 2)
     146    {
     147        siValue =  parts[0];
     148        engValue = parts[1];
     149    }
     150    else if (input.startsWith(";"))
     151    {
     152        engValue = input;
     153        engValue.replace(";", "");
     154    }
     155    else
     156    {
     157        // Trailing ';' or old style without ';'
     158        siValue = input;
     159        siValue.replace(";", "");
     160    }
     161    m_value = (units == ENG_UNITS ? engValue : siValue);
     162    m_otherValue = (units == ENG_UNITS ? siValue : engValue);
     163
     164    if (m_value == "NA" || m_value == "N/A")
     165    {
     166        return "NA";
     167    }
     168    if( m_value == "" && (m_otherValue == "NA" || m_otherValue == "N/A"))
     169    {
     170        return "NA";
     171    }
     172
     173    return 0;
     174}
     175
     176
     177QString Converter::convert(const QString& input, units_t units)
     178{
     179
     180    VERBOSE(VB_MOST, QString( "Converting: ") + input);
     181    QString na = parseValues( input, units);
     182    if ( na != 0)
     183    {
     184        return( na );
     185    }
     186
     187    bool otherHasNumber;
     188    QRegExp number("([-+]?[0-9][0-9.]*)");
     189
     190    if (m_value.contains( number))
     191    {
     192       otherHasNumber = false;
     193    }
     194    else if (m_otherValue.contains( number))
     195    {
     196       otherHasNumber = true;
     197    }
     198    else
     199    {
     200       return QString("NA (") + input + ")";
     201    }
     202
     203    bool ok;
     204    float f = number.cap().toFloat(&ok);
     205    if (!ok)
     206    {
     207        return QString("NA (") + input + ")";
     208    }
     209
     210    if (units == ENG_UNITS && otherHasNumber)
     211    {
     212        f = engValue(f);
     213    }
     214    else if ( units == SI_UNITS && otherHasNumber)
     215    {
     216        f = siValue(f);
     217    }
     218
     219    QString  unit = (units == ENG_UNITS ? m_engUnit: m_metricUnit);
     220    VERBOSE(VB_MOST, QString( "Returning: ") +  format(round(f)) + unit);
     221    return format( round(f)) +  unit;
     222};
     223
     224
     225QString
     226VisibilityConverter::convert(const QString& input, units_t units)
     227{
     228
     229    QString na = parseValues( input, units);
     230    if (na != 0)
     231    {
     232        return( na);
     233    }
     234
     235    QRegExp range = QRegExp( "([0-9]+)[ -]+([0-9]+)");
     236    bool otherHasRange;
     237    if (m_value.contains(range))
     238    {
     239        otherHasRange = false;
     240    }
     241    else if (m_otherValue.contains(range))
     242    {
     243        otherHasRange = true;
     244    }
     245    else
     246    {
     247        return DistanceConverter().convert( input, units);
     248    }
     249
     250    bool     ok;
     251    int      from, to;
     252    from = range.cap(1).toInt( &ok);
     253    if (ok)
     254    {
     255        to = range.cap(2).toInt( &ok);
     256    }
     257    if (!ok)
     258    {
     259        return QString("NA (") + m_value + ")";
     260    }
     261
     262    if (units == ENG_UNITS && otherHasRange)
     263    {
     264        from *= m_factor;
     265        to   *= m_factor;
     266    }
     267    else if (units == SI_UNITS && otherHasRange)
     268    {
     269        from /= m_factor;
     270        to   /= m_factor;
     271    }
     272
     273    QString  unit = (units == ENG_UNITS ? m_engUnit: m_metricUnit);
     274    return QString( "%1 - %2 %3").arg( from).arg( to).arg( unit);
     275};
     276
     277
    45278WeatherScreen *WeatherScreen::loadScreen(MythScreenStack *parent,
    46279                                         ScreenListInfo *screenDefn, int id)
    47280{
    void WeatherScreen::newData(QString loc, units_t units, DataMap data) 
    139372    emit screenReady(this);
    140373}
    141374
    142 QString WeatherScreen::getTemperatureUnit()
    143 {
    144     if (m_units == ENG_UNITS)
    145         return QString::fromUtf8("°") + "F";
    146     else
    147         return QString::fromUtf8("°") + "C";
    148 }
    149 
    150375void WeatherScreen::prepareScreen()
    151376{
    152377    QMap<QString, QString>::iterator itr = m_dataValueMap.begin();
    QString WeatherScreen::formatDataItem(const QString &key, 
    202427        return value + " %";
    203428
    204429    if (key == "pressure")
    205         return value + (m_units == ENG_UNITS ? " in" : " mb");
     430        return PressureConverter().convert( value, m_units);
    206431
    207432    if (key == "visibility")
    208         return value + (m_units == ENG_UNITS ? " mi" : " km");
     433        return VisibilityConverter().convert( value, m_units);
    209434
    210     if (key == "temp" || key == "appt" || key.contains("low",Qt::CaseInsensitive) ||
    211         key.contains("high",Qt::CaseInsensitive))
     435    if (key.contains("temp",Qt::CaseInsensitive)  ||
     436        key.contains("low",Qt::CaseInsensitive)   ||
     437        key.contains("high",Qt::CaseInsensitive) ||
     438        key == "appt")
    212439    {
    213        if ( (value == "NA") || (value == "N/A") )
    214           return value;
    215        else
    216           return value + getTemperatureUnit();
     440        return TempConverter().convert( value, m_units);
    217441    }
    218442
    219443    if (key == "wind_gust" || key == "wind_spdgst" || key == "wind_speed")
    220         return value + (m_units == ENG_UNITS ? " mph" : " kph");
     444        return WindConverter().convert( value, m_units);
    221445
    222446    /*The days of the week will be translated if the script sends elements from
    223447     the enum DaysOfWeek.*/
    QString WeatherScreen::formatDataItem(const QString &key, 
    260484    if (key.startsWith("pop-"))
    261485    {
    262486        if (formatHint == "precipitation")
    263             return value + " mm";
     487            return PrecipConverter().convert( value, m_units);
    264488        else
    265489            return value + " %";
    266490    }
    void AnimatedImageScreen::prepareWidget(MythUIType *widget) 
    383607    }
    384608    return;
    385609}
     610
  • mythweather/weatherScreen.h

    diff --git a/mythweather/weatherScreen.h b/mythweather/weatherScreen.h
    index 4aeb2a1..17d42f0 100644
    a b class WeatherScreen : public MythScreenType 
    6767                                    const QString &formatHint = 0);
    6868    virtual void prepareWidget(MythUIType *widget);
    6969    virtual void prepareScreen();
    70     virtual QString getTemperatureUnit();
    7170    QString formatDataItem(const QString &key,
    7271                           const QString &value,
    7372                           const QString &formatHint = 0);
  • mythweather/weatherSource.cpp

    diff --git a/mythweather/weatherSource.cpp b/mythweather/weatherSource.cpp
    index 57376d4..c0e7f9a 100644
    a b void WeatherSource::startUpdate(bool forceUpdate) 
    535535    QStringList args;
    536536    args.push_back(m_info->fileInfo.absoluteFilePath());
    537537    args.push_back("-u");
    538     args.push_back(m_units == SI_UNITS ? "SI" : "ENG");
     538    args.push_back("SI");
    539539
    540540    if (!m_dir.isEmpty())
    541541    {