Commit 7c982646 authored by Harald Judt's avatar Harald Judt

Implement new units handling and rounding of values.

Replace the old metric/imperial system with a more configurable
solution. Additionally, support optional rounding of values everywhere
in the plugin except on the summary details tab where always the exact
values should be reported.
parent 4d0a9b80
......@@ -33,9 +33,11 @@
#define CHK_NULL(s) ((s) ? g_strdup(s) : g_strdup(""))
#define LOCALE_DOUBLE(value, \
format) (g_strdup_printf(format, \
g_ascii_strtod(value, NULL)))
#define ROUND_TO_INT(default_format) (round ? "%.0f" : default_format)
#define LOCALE_DOUBLE(value, format) \
(g_strdup_printf(format, \
g_ascii_strtod(value, NULL)))
static gboolean
......@@ -67,116 +69,146 @@ string_to_double(const gchar *str,
gchar *
get_data(const xml_time *timeslice,
const unit_systems unit_system,
const data_types type)
const units_config *units,
const data_types type,
gboolean round)
{
const xml_location *loc = NULL;
double val;
gdouble val;
if (timeslice == NULL || timeslice->location == NULL)
if (timeslice == NULL || timeslice->location == NULL || units == NULL)
return g_strdup("");
loc = timeslice->location;
switch (type) {
case ALTITUDE:
if (unit_system == METRIC)
switch (units->altitude) {
case METERS:
return LOCALE_DOUBLE(loc->altitude, "%.0f");
val = g_ascii_strtod(loc->altitude, NULL);
val /= 0.3048;
return g_strdup_printf("%.2f", val);
case FEET:
val = string_to_double(loc->altitude, 0);
val /= 0.3048;
return g_strdup_printf("%.2f", val);
}
case LATITUDE:
return LOCALE_DOUBLE(loc->latitude, "%.4f");
case LONGITUDE:
return LOCALE_DOUBLE(loc->longitude, "%.4f");
case TEMPERATURE:
case TEMPERATURE_RAW:
val = g_ascii_strtod(loc->temperature_value, NULL);
if (unit_system == IMPERIAL &&
case TEMPERATURE: /* source may be in Celsius or Fahrenheit */
val = string_to_double(loc->temperature_value, 0);
if (units->temperature == FAHRENHEIT &&
(!strcmp(loc->temperature_unit, "celcius") ||
!strcmp(loc->temperature_unit, "celsius")))
val = val * 9.0 / 5.0 + 32.0;
else if (unit_system == METRIC &&
else if (units->temperature == CELSIUS &&
!strcmp(loc->temperature_unit, "fahrenheit"))
val = (val - 32.0) * 5.0 / 9.0;
if (type == TEMPERATURE_RAW) {
/* We might want to use the raw temperature value of
* higher precision for calculations. */
return g_strdup_printf("%.1f", val);
} else {
/*
* Round half up for temperatures, according to the
* "Federal Meteorological Handbook No. 1 - Surface
* Weather Observations and Reports September 2005",
* chapter 2.6.3 "Rounding Figures", available at
* http://www.ofcm.gov/fmh-1/fmh1.htm. As a side-effect,
* this approach automatically uses a negative zero "-0"
* for values between -0.5 and 0, which is considered
* important, as in the Celcius scale a value below 0
* indicates freezing.
*/
return g_strdup_printf("%.0f", val);
}
case PRESSURE:
if (unit_system == METRIC)
return LOCALE_DOUBLE(loc->pressure_value, "%.1f");
val = g_ascii_strtod(loc->pressure_value, NULL);
if (unit_system == IMPERIAL)
return g_strdup_printf(ROUND_TO_INT("%.1f"), val);
case PRESSURE: /* source is in hectopascals */
val = string_to_double(loc->pressure_value, 0);
switch (units->pressure) {
case INCH_MERCURY:
val *= 0.03;
case PSI:
val *= 0.01450378911491;
return g_strdup_printf("%.1f", val);
case WIND_SPEED:
val = g_ascii_strtod(loc->wind_speed_mps, NULL);
if (unit_system == IMPERIAL)
val *= 2.2369362920544;
else if (unit_system == METRIC)
case TORR:
val /= 1.333224;
}
return g_strdup_printf(ROUND_TO_INT("%.1f"), val);
case WIND_SPEED: /* source is in meters per hour */
val = string_to_double(loc->wind_speed_mps, 0);
switch (units->windspeed) {
case KMH:
val *= 3.6;
return g_strdup_printf("%.1f", val);
case MPH:
val *= 2.2369362920544;
}
return g_strdup_printf(ROUND_TO_INT("%.1f"), val);
case WIND_BEAUFORT:
return CHK_NULL(loc->wind_speed_beaufort);
case WIND_DIRECTION:
return CHK_NULL(loc->wind_dir_name);
case WIND_DIRECTION_DEG:
return LOCALE_DOUBLE(loc->wind_dir_deg, "%.1f");
case HUMIDITY:
return LOCALE_DOUBLE(loc->humidity_value, "%.1f");
return LOCALE_DOUBLE(loc->humidity_value, ROUND_TO_INT("%.1f"));
case CLOUDS_LOW:
return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_LOW], "%.1f");
return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_LOW],
ROUND_TO_INT("%.1f"));
case CLOUDS_MED:
return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_MED], "%.1f");
return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_MED],
ROUND_TO_INT("%.1f"));
case CLOUDS_HIGH:
return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_HIGH], "%.1f");
return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_HIGH],
ROUND_TO_INT("%.1f"));
case CLOUDINESS:
return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_CLOUDINESS],
"%.1f");
ROUND_TO_INT("%.1f"));
case FOG:
return LOCALE_DOUBLE(loc->fog_percent, "%.1f");
case PRECIPITATIONS:
if (unit_system == METRIC)
return LOCALE_DOUBLE(loc->precipitation_value, "%.1f");
val = g_ascii_strtod(loc->precipitation_value, NULL);
if (unit_system == IMPERIAL)
return LOCALE_DOUBLE(loc->fog_percent, ROUND_TO_INT("%.1f"));
case PRECIPITATIONS: /* source is in millimeters */
val = string_to_double(loc->precipitation_value, 0);
if (units->precipitations == INCHES)
val /= 25.4;
return g_strdup_printf("%.3f", val);
return g_strdup_printf(ROUND_TO_INT("%.1f"), val);
case SYMBOL:
return CHK_NULL(loc->symbol);
}
return g_strdup("");
}
const gchar *
get_unit(const unit_systems unit_system,
get_unit(const units_config *units,
const data_types type)
{
if (units == NULL)
return "";
switch (type) {
case ALTITUDE:
return (unit_system == IMPERIAL) ? _("ft") : _("m");
return (units->altitude == FEET) ? _("ft") : _("m");
case TEMPERATURE:
return (unit_system == IMPERIAL) ? _("°F") : _("°C");
return (units->temperature == FAHRENHEIT) ? _("°F") : _("°C");
case PRESSURE:
return (unit_system == IMPERIAL) ? _("psi") : _("hPa");
switch (units->pressure) {
case HECTOPASCAL:
return _("hPa");
case INCH_MERCURY:
return _("inHg");
case PSI:
return _("psi");
case TORR:
return _("mmHg");
}
case WIND_SPEED:
return (unit_system == IMPERIAL) ? _("mph") : _("km/h");
switch (units->windspeed) {
case KMH:
return _("km/h");
case MPH:
return _("mph");
case MPS:
return _("m/s");
}
case WIND_DIRECTION_DEG:
case LATITUDE:
case LONGITUDE:
......@@ -189,7 +221,7 @@ get_unit(const unit_systems unit_system,
case FOG:
return "%";
case PRECIPITATIONS:
return (unit_system == IMPERIAL) ? _("in") : _("mm");
return (units->precipitations == INCHES) ? _("in") : _("mm");
case SYMBOL:
case WIND_BEAUFORT:
case WIND_DIRECTION:
......
......@@ -42,11 +42,6 @@ typedef enum {
TEMPERATURE_RAW
} data_types;
typedef enum {
IMPERIAL,
METRIC
} unit_systems;
typedef enum {
CELSIUS,
FAHRENHEIT
......@@ -95,10 +90,11 @@ gdouble string_to_double(const gchar *str,
gdouble backup);
gchar *get_data(const xml_time *timeslice,
unit_systems unit_system,
data_types type);
const units_config *units,
data_types type,
gboolean round);
const gchar *get_unit(unit_systems unit_system,
const gchar *get_unit(const units_config *units,
data_types type);
gboolean is_night_time(const xml_astro *astro);
......
......@@ -405,7 +405,6 @@ weather_dump_plugindata(const xfceweather_data *data)
" latitude: %s\n"
" longitude: %s\n"
" location name: %s\n"
" unit system: %d\n"
" night time: %s\n"
" --------------------------------------------\n"
" animation transitions: %s\n"
......@@ -421,7 +420,6 @@ weather_dump_plugindata(const xfceweather_data *data)
data->lat,
data->lon,
data->location_name,
data->unit_system,
YESNO(data->night_time),
YESNO(data->animation_transitions),
data->forecast_days);
......
......@@ -58,8 +58,8 @@ lnk_clicked(GtkTextTag *tag,
g_free(value);
#define APPEND_TEXT_ITEM(text, item) \
rawvalue = get_data(conditions, data->unit_system, item); \
unit = get_unit(data->unit_system, item); \
rawvalue = get_data(conditions, data->units, item, FALSE); \
unit = get_unit(data->units, item); \
value = g_strdup_printf("\t%s%s%s%s%s\n", \
text, text ? ": " : "", \
rawvalue, \
......@@ -398,23 +398,23 @@ create_summary_tab(xfceweather_data *data)
/* wind */
APPEND_BTEXT(_("\nWind\n"));
rawvalue = get_data(conditions, data->unit_system, WIND_SPEED);
wind = translate_wind_speed(rawvalue, data->unit_system);
rawvalue = get_data(conditions, data->units, WIND_SPEED, FALSE);
wind = translate_wind_speed(rawvalue, data->units);
g_free(rawvalue);
rawvalue = get_data(conditions, data->unit_system, WIND_BEAUFORT);
rawvalue = get_data(conditions, data->units, WIND_BEAUFORT, FALSE);
value = g_strdup_printf(_("\t%s: %s (%s on the Beaufort scale)\n"),
_("Speed"), wind, rawvalue);
g_free(rawvalue);
g_free(wind);
APPEND_TEXT_ITEM_REAL(value);
rawvalue = get_data(conditions, data->unit_system, WIND_DIRECTION);
rawvalue = get_data(conditions, data->units, WIND_DIRECTION, FALSE);
wind = translate_wind_direction(rawvalue);
g_free(rawvalue);
rawvalue = get_data(conditions, data->unit_system, WIND_DIRECTION_DEG);
rawvalue = get_data(conditions, data->units, WIND_DIRECTION_DEG, FALSE);
value = g_strdup_printf("\t%s: %s (%s%s)\n", _("Direction"),
wind, rawvalue,
get_unit(data->unit_system, WIND_DIRECTION_DEG));
get_unit(data->units, WIND_DIRECTION_DEG));
g_free(rawvalue);
g_free(wind);
APPEND_TEXT_ITEM_REAL(value);
......@@ -596,7 +596,7 @@ make_forecast(xfceweather_data *data)
fcdata = make_forecast_data(data->weatherdata, i, daytime);
if (fcdata != NULL) {
if (fcdata->location != NULL) {
rawvalue = get_data(fcdata, data->unit_system, SYMBOL);
rawvalue = get_data(fcdata, data->units, SYMBOL, FALSE);
icon = get_icon(data->icon_theme, rawvalue, 48,
(daytime == NIGHT));
g_free(rawvalue);
......@@ -606,10 +606,11 @@ make_forecast(xfceweather_data *data)
if (G_LIKELY(icon))
g_object_unref(G_OBJECT(icon));
rawvalue = get_data(fcdata, data->unit_system, SYMBOL);
value = g_strdup_printf("%s",
translate_desc(rawvalue,
(daytime == NIGHT)));
rawvalue = get_data(fcdata, data->units, SYMBOL, FALSE);
value =
g_strdup_printf("%s",
translate_desc(rawvalue,
(daytime == NIGHT)));
g_free(rawvalue);
label = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(label), value);
......@@ -620,10 +621,11 @@ make_forecast(xfceweather_data *data)
TRUE, TRUE, 0);
g_free(value);
rawvalue = get_data(fcdata, data->unit_system, TEMPERATURE);
rawvalue = get_data(fcdata, data->units,
TEMPERATURE, data->round);
value = g_strdup_printf("%s %s",
rawvalue,
get_unit(data->unit_system,
get_unit(data->units,
TEMPERATURE));
g_free(rawvalue);
label = gtk_label_new(value);
......@@ -634,14 +636,15 @@ make_forecast(xfceweather_data *data)
TRUE, TRUE, 0);
g_free(value);
rawvalue = get_data(fcdata, data->unit_system,
WIND_DIRECTION);
rawvalue = get_data(fcdata, data->units,
WIND_DIRECTION, FALSE);
wind_direction = translate_wind_direction(rawvalue);
wind_speed = get_data(fcdata, data->unit_system, WIND_SPEED);
wind_speed = get_data(fcdata, data->units,
WIND_SPEED, data->round);
value = g_strdup_printf("%s %s %s",
wind_direction,
wind_speed,
get_unit(data->unit_system,
get_unit(data->units,
WIND_SPEED));
g_free(wind_speed);
g_free(wind_direction);
......@@ -767,7 +770,7 @@ create_summary_window (xfceweather_data *data)
conditions = get_current_conditions(data->weatherdata);
symbol = get_data(conditions, data->unit_system, SYMBOL);
symbol = get_data(conditions, data->units, SYMBOL, FALSE);
icon = get_icon(data->icon_theme, symbol, 48, data->night_time);
g_free(symbol);
......
......@@ -278,7 +278,7 @@ translate_wind_direction(const gchar *wdir)
/* Return "calm", "N/A" or a number */
gchar *
translate_wind_speed(const gchar *wspeed,
const unit_systems unit_system)
const units_config *units)
{
gchar *wspeed_loc;
......@@ -288,7 +288,7 @@ translate_wind_speed(const gchar *wspeed,
wspeed_loc = g_strdup(_("N/A"));
else {
wspeed_loc =
g_strdup_printf("%s %s", wspeed, get_unit(unit_system, WIND_SPEED));
g_strdup_printf("%s %s", wspeed, get_unit(units, WIND_SPEED));
}
return wspeed_loc;
}
......@@ -35,7 +35,7 @@ gchar *translate_day(gint weekday);
gchar *translate_wind_direction(const gchar *wdir);
gchar *translate_wind_speed(const gchar *wspeed,
unit_systems unit_system);
const units_config *units);
G_END_DECLS
......
......@@ -43,13 +43,13 @@
#define BORDER 8
#define CONNECTION_TIMEOUT (10) /* connection timeout in seconds */
#define DATA_AND_UNIT(var, item) \
value = get_data(conditions, data->unit_system, item); \
unit = get_unit(data->unit_system, item); \
var = g_strdup_printf("%s%s%s", \
value, \
strcmp(unit, "°") ? " " : "", \
unit); \
#define DATA_AND_UNIT(var, item) \
value = get_data(conditions, data->units, item, data->round); \
unit = get_unit(data->units, item); \
var = g_strdup_printf("%s%s%s", \
value, \
strcmp(unit, "°") ? " " : "", \
unit); \
g_free(value);
......@@ -151,14 +151,14 @@ make_label(const xfceweather_data *data,
/* get current weather conditions */
conditions = get_current_conditions(data->weatherdata);
rawvalue = get_data(conditions, data->unit_system, type);
rawvalue = get_data(conditions, data->units, type, data->round);
switch (type) {
case WIND_DIRECTION:
value = translate_wind_direction(rawvalue);
break;
case WIND_SPEED:
value = translate_wind_speed(rawvalue, data->unit_system);
value = translate_wind_speed(rawvalue, data->units);
break;
default:
value = NULL;
......@@ -171,7 +171,7 @@ make_label(const xfceweather_data *data,
txtsize, lbl, value);
g_free(value);
} else {
unit = get_unit(data->unit_system, type);
unit = get_unit(data->units, type);
str = g_strdup_printf("<span size=\"%s\">%s: %s%s%s</span>",
txtsize, lbl, rawvalue,
strcmp(unit, "°") ? " " : "", unit);
......@@ -182,7 +182,7 @@ make_label(const xfceweather_data *data,
txtsize, value);
g_free(value);
} else {
unit = get_unit(data->unit_system, type);
unit = get_unit(data->units, type);
str = g_strdup_printf("<span size=\"%s\">%s%s%s</span>",
txtsize, rawvalue,
strcmp(unit, "°") ? " " : "", unit);
......@@ -211,7 +211,7 @@ update_icon(xfceweather_data *data)
/* set icon according to current weather conditions */
conditions = get_current_conditions(data->weatherdata);
str = get_data(conditions, data->unit_system, SYMBOL);
str = get_data(conditions, data->units, SYMBOL, data->round);
icon = get_icon(data->icon_theme, str, size, data->night_time);
g_free(str);
gtk_image_set_from_pixbuf(GTK_IMAGE(data->iconimage), icon);
......@@ -519,7 +519,21 @@ xfceweather_read_config(XfcePanelPlugin *plugin,
data->location_name = g_strdup(value);
}
data->unit_system = xfce_rc_read_int_entry(rc, "unit_system", METRIC);
if (data->units)
g_slice_free(units_config, data->units);
data->units = g_slice_new0(units_config);
data->units->temperature =
xfce_rc_read_int_entry(rc, "units_temperature", CELSIUS);
data->units->pressure =
xfce_rc_read_int_entry(rc, "units_pressure", HECTOPASCAL);
data->units->windspeed =
xfce_rc_read_int_entry(rc, "units_windspeed", KMH);
data->units->precipitations =
xfce_rc_read_int_entry(rc, "units_precipitations", MILLIMETERS);
data->units->altitude =
xfce_rc_read_int_entry(rc, "units_altitude", METERS);
data->round = xfce_rc_read_bool_entry(rc, "round", TRUE);
val = xfce_rc_read_int_entry(rc, "forecast_days", DEFAULT_FORECAST_DAYS);
data->forecast_days =
......@@ -571,7 +585,8 @@ xfceweather_write_config(XfcePanelPlugin *plugin,
if (!rc)
return;
xfce_rc_write_int_entry(rc, "unit_system", data->unit_system);
if (data->location_name)
xfce_rc_write_entry(rc, "loc_name", data->location_name);
if (data->lat)
xfce_rc_write_entry(rc, "lat", data->lat);
......@@ -579,8 +594,14 @@ xfceweather_write_config(XfcePanelPlugin *plugin,
if (data->lon)
xfce_rc_write_entry(rc, "lon", data->lon);
if (data->location_name)
xfce_rc_write_entry(rc, "loc_name", data->location_name);
xfce_rc_write_int_entry(rc, "units_temperature", data->units->temperature);
xfce_rc_write_int_entry(rc, "units_pressure", data->units->pressure);
xfce_rc_write_int_entry(rc, "units_windspeed", data->units->windspeed);
xfce_rc_write_int_entry(rc, "units_precipitations",
data->units->precipitations);
xfce_rc_write_int_entry(rc, "units_altitude", data->units->altitude);
xfce_rc_write_bool_entry(rc, "round", data->round);
xfce_rc_write_int_entry(rc, "forecast_days", data->forecast_days);
......@@ -814,7 +835,7 @@ weather_get_tooltip_text(const xfceweather_data *data)
else
sunval = g_strdup_printf("");
sym = get_data(conditions, data->unit_system, SYMBOL);
sym = get_data(conditions, data->units, SYMBOL, FALSE);
DATA_AND_UNIT(symbol, SYMBOL);
DATA_AND_UNIT(alt, ALTITUDE);
DATA_AND_UNIT(lat, LATITUDE);
......@@ -901,7 +922,7 @@ weather_get_tooltip_cb(GtkWidget *widget,
}
conditions = get_current_conditions(data->weatherdata);
rawvalue = get_data(conditions, data->unit_system, SYMBOL);
rawvalue = get_data(conditions, data->units, SYMBOL, data->round);
icon = get_icon(data->icon_theme, rawvalue, 128, data->night_time);
g_free(rawvalue);
gtk_tooltip_set_icon(tooltip, icon);
......@@ -924,7 +945,6 @@ xfceweather_create_control(XfcePanelPlugin *plugin)
/* Initialize with sane default values */
data->plugin = plugin;
data->unit_system = METRIC;
data->units = g_slice_new0(units_config);
data->weatherdata = NULL;
data->forecast_days = DEFAULT_FORECAST_DAYS;
......
......@@ -61,8 +61,8 @@ typedef struct {
gchar *lon;
gchar *location_name;
unit_systems unit_system;
units_config *units;
gboolean round;
xml_weather *weatherdata;
xml_astro *astrodata;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment