From f7d1f84fe3f65b97d17f72bdbe21bc455d81a803 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 18 Feb 2020 15:59:32 +0000 Subject: [PATCH 1/3] Add arrows to ground track to show direction satellite is moving in --- src/gtk-sat-map-ground-track.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/gtk-sat-map-ground-track.c b/src/gtk-sat-map-ground-track.c index f54d611e..1519e01b 100644 --- a/src/gtk-sat-map-ground-track.c +++ b/src/gtk-sat-map-ground-track.c @@ -313,6 +313,7 @@ static void create_polylines(GtkSatMap * satmap, sat_t * sat, qth_t * qth, guint start; guint i, j, n, num_points; guint32 col; + gboolean start_not_end; (void)sat; (void)qth; @@ -327,6 +328,10 @@ static void create_polylines(GtkSatMap * satmap, sat_t * sat, qth_t * qth, MOD_CFG_MAP_SECTION, MOD_CFG_MAP_TRACK_COL, SAT_CFG_INT_MAP_TRACK_COL); + /* Determine which end arrow heads should be drawn, depending on direction + satellite is moving in, which is determined by its inclination. */ + start_not_end = sat->tle.xincl > 90.0; + /* loop over each SSP */ for (i = 0; i < n; i++) { @@ -375,6 +380,16 @@ static void create_polylines(GtkSatMap * satmap, sat_t * sat, qth_t * qth, CAIRO_LINE_CAP_SQUARE, "line-join", CAIRO_LINE_JOIN_MITER, + "end-arrow", + !start_not_end, + "start-arrow", + start_not_end, + "arrow-length", + 10.0, + "arrow-tip-length", + 8.0, + "arrow-width", + 8.0, NULL); goo_canvas_points_unref(gpoints); goo_canvas_item_model_lower(line, obj->marker); @@ -438,7 +453,13 @@ static void create_polylines(GtkSatMap * satmap, sat_t * sat, qth_t * qth, "stroke-color-rgba", col, "line-cap", CAIRO_LINE_CAP_SQUARE, "line-join", - CAIRO_LINE_JOIN_MITER, NULL); + CAIRO_LINE_JOIN_MITER, + "end-arrow", !start_not_end, + "start-arrow", start_not_end, + "arrow-length", 10.0, + "arrow-tip-length", 8.0, + "arrow-width", 8.0, + NULL); goo_canvas_points_unref(gpoints); goo_canvas_item_model_lower(line, obj->marker); From c87301b4c25230688ef49f5c33bcb88e8c6e6b57 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 20 Feb 2020 23:53:28 +0000 Subject: [PATCH 2/3] Add option to automatically display ground track for selected satellite. Ground track is then cleared when another satellite is selected, unless ground track was manually enabled for the satellite via the menu. --- src/config-keys.h | 1 + src/gtk-sat-map.c | 61 +++++++++++++++++++++++++++++++++++++ src/sat-cfg.h | 1 + src/sat-pref-map-view.c | 67 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+) diff --git a/src/config-keys.h b/src/config-keys.h index 7647b82f..31288881 100644 --- a/src/config-keys.h +++ b/src/config-keys.h @@ -113,6 +113,7 @@ #define MOD_CFG_MAP_SHADOW_ALPHA "SHADOW_ALPHA" #define MOD_CFG_MAP_SHOWTRACKS "SHOWTRACKS" #define MOD_CFG_MAP_HIDECOVS "HIDECOVS" +#define MOD_CFG_MAP_AUTO_GROUND_TRACK "AUTO_GROUND_TRACK" /* polar view specific */ #define MOD_CFG_POLAR_SECTION "POLAR" diff --git a/src/gtk-sat-map.c b/src/gtk-sat-map.c index ea8d38b7..6737e51b 100644 --- a/src/gtk-sat-map.c +++ b/src/gtk-sat-map.c @@ -74,6 +74,8 @@ static gboolean on_button_press(GooCanvasItem * item, static gboolean on_button_release(GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data); +static void clear_auto_ground_tracks(gpointer key, gpointer val, + gpointer data); static void clear_selection(gpointer key, gpointer val, gpointer data); static void load_map_file(GtkSatMap * satmap, float clon); static GooCanvasItemModel *create_canvas_model(GtkSatMap * satmap); @@ -823,6 +825,8 @@ static gboolean on_button_release(GooCanvasItem * item, gint *catpoint = NULL; sat_map_obj_t *obj = NULL; guint32 col; + sat_t *sat = NULL; + gboolean auto_ground_track; (void)target; @@ -843,6 +847,18 @@ static gboolean on_button_release(GooCanvasItem * item, } else { + auto_ground_track = mod_cfg_get_bool(satmap->cfgdata, + MOD_CFG_MAP_SECTION, + MOD_CFG_MAP_AUTO_GROUND_TRACK, + SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK); + + if (auto_ground_track) + { + /* Clear auto-enabled ground trackss. */ + g_hash_table_foreach(satmap->obj, clear_auto_ground_tracks, + satmap); + } + obj->selected = !obj->selected; if (obj->selected) @@ -874,6 +890,23 @@ static gboolean on_button_release(GooCanvasItem * item, if (obj->oldrcnum == 2) g_object_set(obj->range2, "stroke-color-rgba", col, NULL); + if (auto_ground_track) + { + /* Create ground track for newly selected satellite. */ + sat = SAT(g_hash_table_lookup(satmap->sats, catpoint)); + if (sat != NULL) + { + if (!obj->showtrack) + { + obj->showtrack = TRUE; + /* create ground track */ + ground_track_create(satmap, sat, satmap->qth, obj); + /* do not add to satmap->showtracks, that's just for + * sats where it has manually been enabled. */ + } + } + } + /* clear other selections */ g_hash_table_foreach(satmap->obj, clear_selection, catpoint); } @@ -887,6 +920,34 @@ static gboolean on_button_release(GooCanvasItem * item, return TRUE; } +/* Delete ground tracks that were automatically enabled for the selected + * satellite. */ + +static void clear_auto_ground_tracks(gpointer key, gpointer val, gpointer data) +{ + GtkSatMap *satmap = GTK_SAT_MAP(data); + sat_map_obj_t *obj = SAT_MAP_OBJ(val); + sat_t *sat = NULL; + gint *catpoint = key; + + if (obj->selected) + { + sat = SAT(g_hash_table_lookup(satmap->sats, catpoint)); + if (sat != NULL) + { + /* If ground track was auto enabled, this sat will not be in + * showtracks hash table. Don't use value in hash table, + * just whether it exists */ + if (!g_hash_table_lookup_extended(satmap->showtracks, + &(sat->tle.catnr), NULL, NULL)) + { + obj->showtrack = FALSE; + ground_track_delete(satmap, sat, satmap->qth, obj, TRUE); + } + } + } +} + static void clear_selection(gpointer key, gpointer val, gpointer data) { gint *old = key; diff --git a/src/sat-cfg.h b/src/sat-cfg.h index 446e19fa..49d8b019 100644 --- a/src/sat-cfg.h +++ b/src/sat-cfg.h @@ -43,6 +43,7 @@ typedef enum { SAT_CFG_BOOL_MAP_SHOW_CURS_TRACK, /*!< Track mouse cursor on map. */ SAT_CFG_BOOL_MAP_SHOW_GRID, /*!< Show grid on map. */ SAT_CFG_BOOL_MAP_KEEP_RATIO, /*!< Keep original aspect ratio */ + SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK, /*!< Whether to automatically show ground track for selected satellite */ SAT_CFG_BOOL_POL_SHOW_QTH_INFO, /*!< Show QTH info on polar plot */ SAT_CFG_BOOL_POL_SHOW_NEXT_EV, /*!< Show next event on polar plot */ SAT_CFG_BOOL_POL_SHOW_CURS_TRACK, /*!< Track mouse cursor on polar plot. */ diff --git a/src/sat-pref-map-view.c b/src/sat-pref-map-view.c index c107a326..c1230dd3 100644 --- a/src/sat-pref-map-view.c +++ b/src/sat-pref-map-view.c @@ -44,6 +44,7 @@ static GtkWidget *satc, *ssatc, *trackc; static GtkWidget *covc, *infofg, *infobg; static GtkWidget *terminator, *globe_shadow; static GtkWidget *shadow; +static GtkWidget *auto_ground_track; /* ground track orbit number selector */ static GtkWidget *orbit; @@ -248,6 +249,10 @@ static void reset_cb(GtkWidget * button, gpointer cfg) gtk_range_set_value(GTK_RANGE(shadow), sat_cfg_get_int_def(SAT_CFG_INT_MAP_SHADOW_ALPHA)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(auto_ground_track), + sat_cfg_get_bool_def + (SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK)); + /* ground track orbits */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(orbit), sat_cfg_get_int_def @@ -329,6 +334,10 @@ static void reset_cb(GtkWidget * button, gpointer cfg) gtk_range_set_value(GTK_RANGE(shadow), sat_cfg_get_int(SAT_CFG_INT_MAP_SHADOW_ALPHA)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(auto_ground_track), + sat_cfg_get_bool + (SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK)); + /* ground track orbits */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(orbit), sat_cfg_get_int(SAT_CFG_INT_MAP_TRACK_NUM)); @@ -454,6 +463,11 @@ void sat_pref_map_view_ok(GKeyFile * cfg) (gint) gtk_range_get_value(GTK_RANGE(shadow))); + g_key_file_set_boolean(cfg, MOD_CFG_MAP_SECTION, + MOD_CFG_MAP_AUTO_GROUND_TRACK, + gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(auto_ground_track))); + /* orbit */ g_key_file_set_integer(cfg, MOD_CFG_MAP_SECTION, MOD_CFG_MAP_TRACK_NUM, @@ -539,6 +553,9 @@ void sat_pref_map_view_ok(GKeyFile * cfg) sat_cfg_set_int(SAT_CFG_INT_MAP_SHADOW_ALPHA, (gint) gtk_range_get_value(GTK_RANGE(shadow))); + sat_cfg_set_bool(SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON + (auto_ground_track))); /* orbit */ sat_cfg_set_int(SAT_CFG_INT_MAP_TRACK_NUM, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON @@ -602,6 +619,9 @@ void sat_pref_map_view_ok(GKeyFile * cfg) g_key_file_remove_key(cfg, MOD_CFG_MAP_SECTION, MOD_CFG_MAP_SHADOW_ALPHA, NULL); + g_key_file_remove_key(cfg, + MOD_CFG_MAP_SECTION, + MOD_CFG_MAP_AUTO_GROUND_TRACK, NULL); g_key_file_remove_key(cfg, MOD_CFG_MAP_SECTION, MOD_CFG_MAP_TRACK_NUM, NULL); @@ -634,6 +654,8 @@ void sat_pref_map_view_ok(GKeyFile * cfg) sat_cfg_reset_int(SAT_CFG_INT_MAP_INFO_BGD_COL); sat_cfg_reset_int(SAT_CFG_INT_MAP_SHADOW_ALPHA); + sat_cfg_reset_bool(SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK); + /* orbit */ sat_cfg_reset_int(SAT_CFG_INT_MAP_TRACK_NUM); @@ -1194,6 +1216,50 @@ static void create_colour_selectors(GKeyFile * cfg, GtkBox * vbox) NULL); } +/** + * Create auto ground track display selector widget. + * + * @param cfg The module configuration or NULL in global mode. + * @param vbox The container box in which the widgets should be packed into. + * + * This function creates the widgets for determining if ground tracks should + * be displayed when a satellite is selected. + * + */ +static void create_auto_ground_track(GKeyFile * cfg, GtkBox * vbox) +{ + GtkWidget *label; + GtkWidget *hbox; + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); + gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE); + gtk_box_pack_start(vbox, hbox, FALSE, TRUE, 0); + + auto_ground_track = gtk_check_button_new_with_label( + _("Always display ground track for selected satellite")); + gtk_widget_set_tooltip_text(auto_ground_track, + _("Ground track will be enabled for a satellite " + "when selected and cleared when another is selected " + "(unless manually enabled via the menu)")); + if (cfg != NULL) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(auto_ground_track), + mod_cfg_get_bool(cfg, + MOD_CFG_MAP_SECTION, + MOD_CFG_MAP_AUTO_GROUND_TRACK, + SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK)); + } + else + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(auto_ground_track), + sat_cfg_get_bool + (SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK)); + } + g_signal_connect(auto_ground_track, "toggled", G_CALLBACK(content_changed), NULL); + gtk_box_pack_start(GTK_BOX(hbox), auto_ground_track, FALSE, TRUE, 0); + +} + /** * Create orbit number selector widget. * @@ -1355,6 +1421,7 @@ GtkWidget *sat_pref_map_view_create(GKeyFile * cfg) gtk_box_pack_start(GTK_BOX(vbox), gtk_separator_new(GTK_ORIENTATION_HORIZONTAL), FALSE, TRUE, 5); + create_auto_ground_track(cfg, GTK_BOX(vbox)); create_orbit_selector(cfg, GTK_BOX(vbox)); create_center_selector(cfg, GTK_BOX(vbox)); gtk_box_pack_start(GTK_BOX(vbox), From fbb4f3f0d55fdd93950156cb2de0de276e37d387 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Sun, 23 Feb 2020 14:47:05 +0000 Subject: [PATCH 3/3] Add support for fractional number of orbits < 2. When number of orbits < 2, start ground track 25% of orbit behind current satellite position --- src/gtk-sat-map-ground-track.c | 180 ++++++++++++++++++++++----------- src/mod-cfg-get-param.c | 32 ++++++ src/mod-cfg-get-param.h | 2 + src/sat-cfg.c | 117 ++++++++++++++++++++- src/sat-cfg.h | 11 +- src/sat-pref-map-view.c | 51 ++++++---- 6 files changed, 313 insertions(+), 80 deletions(-) diff --git a/src/gtk-sat-map-ground-track.c b/src/gtk-sat-map-ground-track.c index 1519e01b..9c43d1cf 100644 --- a/src/gtk-sat-map-ground-track.c +++ b/src/gtk-sat-map-ground-track.c @@ -73,6 +73,11 @@ void ground_track_create(GtkSatMap * satmap, sat_t * sat, qth_t * qth, double t0; /* time when this_orbit starts */ double t; ssp_t *this_ssp; + double track_num; + double target_phase; + double prev_phase; + double total_phase; + gboolean wrap; sat_log_log(SAT_LOG_LEVEL_DEBUG, _("%s: Creating ground track for %s"), @@ -83,76 +88,133 @@ void ground_track_create(GtkSatMap * satmap, sat_t * sat, qth_t * qth, /* get configuration parameters */ this_orbit = sat->orbit; - max_orbit = sat->orbit - 1 + mod_cfg_get_int(satmap->cfgdata, - MOD_CFG_MAP_SECTION, - MOD_CFG_MAP_TRACK_NUM, - SAT_CFG_INT_MAP_TRACK_NUM); - - sat_log_log(SAT_LOG_LEVEL_DEBUG, - _("%s: Start orbit: %d"), __func__, this_orbit); - sat_log_log(SAT_LOG_LEVEL_DEBUG, - _("%s: End orbit %d"), __func__, max_orbit); - - /* find the time when the current orbit started */ - - /* Iterate backwards in time until we reach sat->orbit < this_orbit. - Use predict_calc from predict-tools.c as SGP/SDP driver. - As a built-in safety, we stop iteration if the orbit crossing is - more than 24 hours back in time. - */ - t0 = satmap->tstamp; //get_current_daynum (); - /* use == instead of >= as it is more robust */ - for (t = t0; (sat->orbit == this_orbit) && ((t + 1.0) > t0); t -= 0.0007) - predict_calc(sat, qth, t); - - /* set it so that we are in the same orbit as this_orbit - and not a different one */ - t += 2 * 0.0007; - t0 = t; - predict_calc(sat, qth, t0); + track_num = mod_cfg_get_double(satmap->cfgdata, MOD_CFG_MAP_SECTION, + MOD_CFG_MAP_TRACK_NUM, + SAT_CFG_DOUBLE_MAP_TRACK_NUM); + + /* If number of orbits to draw is less than 2, we start the track 25% or an + * orbit behind the satellites current position. Otherwise it starts at the + * start of the orbit. */ + if (track_num < 2.0) + { + /* Start a quarter of an orbit ago */ + if (sat->phase <= 90.0) + { + target_phase = sat->phase + 360.0 - 90.0; + wrap = TRUE; + } + else + { + target_phase = sat->phase - 90.0; + wrap = FALSE; + } + for (t = satmap->tstamp; (wrap && (sat->phase <= 90.0)) || (sat->phase > target_phase); t -= 0.0007) + predict_calc(sat, qth, t); + t += 0.0007; + + /* Move ahead user-defined number of orbits (or parts of) */ + prev_phase = sat->phase; + total_phase = 0.0; + while ((total_phase < 360.0 * track_num) && (!decayed(sat))) + { + /* We use 30 sec time steps. If resolution is too fine, the + line drawing routine will filter out unnecessary points + */ + t += 0.00035; + predict_calc(sat, qth, t); + if (sat->phase < prev_phase) // have we wrapped? + total_phase += sat->phase + 360.0 - prev_phase; + else + total_phase += sat->phase - prev_phase; + prev_phase = sat->phase; - sat_log_log(SAT_LOG_LEVEL_DEBUG, - _("%s: T0: %f (%d)"), __func__, t0, sat->orbit); + /* store this SSP */ + this_ssp = g_try_new(ssp_t, 1); + if (this_ssp == NULL) + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: MAYDAY: Insufficient memory for ground track!"), + __func__); + return; + } - /* calculate (lat,lon) for the required orbits */ - while ((sat->orbit <= max_orbit) && - (sat->orbit >= this_orbit) && (!decayed(sat))) + this_ssp->lat = sat->ssplat; + this_ssp->lon = sat->ssplon; + obj->track_data.latlon = + g_slist_prepend(obj->track_data.latlon, this_ssp); + } + } + else { - /* We use 30 sec time steps. If resolution is too fine, the - line drawing routine will filter out unnecessary points - */ - t += 0.00035; - predict_calc(sat, qth, t); + max_orbit = sat->orbit - 1 + (long)track_num; + + sat_log_log(SAT_LOG_LEVEL_DEBUG, + _("%s: Start orbit: %d"), __func__, this_orbit); + sat_log_log(SAT_LOG_LEVEL_DEBUG, + _("%s: End orbit %d"), __func__, max_orbit); - /* store this SSP */ + /* find the time when the current orbit started */ - /* Note: g_slist_append() has to traverse the entire list to find the end, which - is inefficient when adding multiple elements. Therefore, we use g_slist_prepend() - and reverse the entire list when we are done. + /* Iterate backwards in time until we reach sat->orbit < this_orbit. + Use predict_calc from predict-tools.c as SGP/SDP driver. + As a built-in safety, we stop iteration if the orbit crossing is + more than 24 hours back in time. */ - this_ssp = g_try_new(ssp_t, 1); + t0 = satmap->tstamp; //get_current_daynum (); + /* use == instead of >= as it is more robust */ + for (t = t0; (sat->orbit == this_orbit) && ((t + 1.0) > t0); t -= 0.0007) + predict_calc(sat, qth, t); + + /* set it so that we are in the same orbit as this_orbit + and not a different one */ + t += 2 * 0.0007; + t0 = t; + predict_calc(sat, qth, t0); + + sat_log_log(SAT_LOG_LEVEL_DEBUG, + _("%s: T0: %f (%d)"), __func__, t0, sat->orbit); + + /* calculate (lat,lon) for the required orbits */ + while ((sat->orbit <= max_orbit) && + (sat->orbit >= this_orbit) && (!decayed(sat))) + { + /* We use 30 sec time steps. If resolution is too fine, the + line drawing routine will filter out unnecessary points + */ + t += 0.00035; + predict_calc(sat, qth, t); + + /* store this SSP */ + + /* Note: g_slist_append() has to traverse the entire list to find the end, which + is inefficient when adding multiple elements. Therefore, we use g_slist_prepend() + and reverse the entire list when we are done. + */ + this_ssp = g_try_new(ssp_t, 1); + + if (this_ssp == NULL) + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: MAYDAY: Insufficient memory for ground track!"), + __func__); + return; + } - if (this_ssp == NULL) + this_ssp->lat = sat->ssplat; + this_ssp->lon = sat->ssplon; + obj->track_data.latlon = + g_slist_prepend(obj->track_data.latlon, this_ssp); + + } + + /* log if there is a problem with the orbit calculation */ + if (sat->orbit != (max_orbit + 1)) { sat_log_log(SAT_LOG_LEVEL_ERROR, - _("%s: MAYDAY: Insufficient memory for ground track!"), - __func__); + _("%s: Problem computing ground track for %s"), + __func__, sat->nickname); return; } - - this_ssp->lat = sat->ssplat; - this_ssp->lon = sat->ssplon; - obj->track_data.latlon = - g_slist_prepend(obj->track_data.latlon, this_ssp); - - } - /* log if there is a problem with the orbit calculation */ - if (sat->orbit != (max_orbit + 1)) - { - sat_log_log(SAT_LOG_LEVEL_ERROR, - _("%s: Problem computing ground track for %s"), - __func__, sat->nickname); - return; } /* Reset satellite structure to eliminate glitches in single sat diff --git a/src/mod-cfg-get-param.c b/src/mod-cfg-get-param.c index 79e3da97..ec6fb391 100644 --- a/src/mod-cfg-get-param.c +++ b/src/mod-cfg-get-param.c @@ -155,6 +155,38 @@ gchar *mod_cfg_get_str(GKeyFile * f, const gchar * sec, return param; } +gdouble mod_cfg_get_double(GKeyFile * f, const gchar * sec, const gchar * key, + sat_cfg_double_e p) +{ + GError *error = NULL; + gdouble param; + + /* check whether parameter is present in GKeyFile */ + if (g_key_file_has_key(f, sec, key, NULL)) + { + param = g_key_file_get_double(f, sec, key, &error); + + if (error != NULL) + { + sat_log_log(SAT_LOG_LEVEL_WARN, + _("%s: Failed to read double (%s)"), + __func__, error->message); + + g_clear_error(&error); + + /* get a timeout from global config */ + param = sat_cfg_get_double(p); + } + } + /* get value from sat-cfg */ + else + { + param = sat_cfg_get_double(p); + } + + return param; +} + /** * \brief Load an integer list into a hash table that uses the * existinence of datain the hash as a boolean. diff --git a/src/mod-cfg-get-param.h b/src/mod-cfg-get-param.h index 8a6ffd2e..d93c6d4b 100644 --- a/src/mod-cfg-get-param.h +++ b/src/mod-cfg-get-param.h @@ -35,6 +35,8 @@ gint mod_cfg_get_int(GKeyFile * f, const gchar * sec, const gchar * key, sat_cfg_int_e p); gchar *mod_cfg_get_str(GKeyFile * f, const gchar * sec, const gchar * key, sat_cfg_str_e p); +gdouble mod_cfg_get_double(GKeyFile * f, const gchar * sec, + const gchar * key, sat_cfg_double_e p); void mod_cfg_get_integer_list_boolean(GKeyFile * cfgdata, const gchar * section, const gchar * key, diff --git a/src/sat-cfg.c b/src/sat-cfg.c index f86b7478..fd9a32d1 100644 --- a/src/sat-cfg.c +++ b/src/sat-cfg.c @@ -109,6 +109,13 @@ typedef struct { gchar *defval; /*!< The default value */ } sat_cfg_str_t; +/** Structure representing an double value */ +typedef struct { + gchar *group; /*!< The configration group */ + gchar *key; /*!< The configuration key */ + gdouble defval; /*!< The default value */ +} sat_cfg_double_t; + /** Array containing the boolean configuration values */ sat_cfg_bool_t sat_cfg_bool[SAT_CFG_BOOL_NUM] = { {"GLOBAL", "USE_LOCAL_TIME", FALSE}, @@ -161,7 +168,6 @@ sat_cfg_int_t sat_cfg_int[SAT_CFG_INT_NUM] = { {"MODULES", "MAP_EARTH_SHADOW_COLOUR", 0x00000060}, {"MODULES", "MAP_TICK_COLOUR", 0x7F7F7FC8}, {"MODULES", "MAP_TRACK_COLOUR", 0xFF1200BB}, - {"MODULES", "MAP_TRACK_NUM", 3}, {"MODULES", "MAP_SHADOW_ALPHA", 0xDD}, {"MODULES", "POLAR_REFRESH", 3}, {"MODULES", "POLAR_CHART_ORIENT", POLAR_VIEW_NESW}, @@ -245,6 +251,11 @@ sat_cfg_str_t sat_cfg_str[SAT_CFG_STR_NUM] = { {"PREDICT", "SAVE_DIR", NULL} }; +/** Array containing the double configuration parameters */ +sat_cfg_double_t sat_cfg_double[SAT_CFG_DOUBLE_NUM] = { + {"MODULES", "MAP_TRACK_NUM", 3.0}, +}; + /* The configuration data buffer */ static GKeyFile *config = NULL; @@ -727,3 +738,107 @@ void sat_cfg_reset_int(sat_cfg_int_e param) _("%s: Unknown INT param index (%d)\n"), __func__, param); } } + +gdouble sat_cfg_get_double(sat_cfg_double_e param) +{ + gdouble value = 0.0; + GError *error = NULL; + + if (param < SAT_CFG_DOUBLE_NUM) + { + if (config == NULL) + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: Module not initialised\n"), __func__); + + /* return default value */ + value = sat_cfg_double[param].defval; + } + else + { + /* fetch value */ + value = g_key_file_get_double(config, + sat_cfg_double[param].group, + sat_cfg_double[param].key, &error); + + if (error != NULL) + { + g_clear_error(&error); + value = sat_cfg_double[param].defval; + } + } + + } + else + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: Unknown INT param index (%d)\n"), __func__, param); + } + + return value; +} + +gdouble sat_cfg_get_double_def(sat_cfg_double_e param) +{ + gdouble value = 0.0; + + if (param < SAT_CFG_DOUBLE_NUM) + { + value = sat_cfg_double[param].defval; + } + else + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: Unknown double param index (%d)\n"), __func__, param); + } + + return value; +} + +void sat_cfg_set_double(sat_cfg_double_e param, gdouble value) +{ + if (param < SAT_CFG_DOUBLE_NUM) + { + if (config == NULL) + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: Module not initialised\n"), __func__); + } + else + { + g_key_file_set_double(config, + sat_cfg_double[param].group, + sat_cfg_double[param].key, value); + } + + } + else + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: Unknown double param index (%d)\n"), __func__, param); + } +} + +void sat_cfg_reset_double(sat_cfg_double_e param) +{ + if (param < SAT_CFG_DOUBLE_NUM) + { + if (config == NULL) + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: Module not initialised\n"), __func__); + } + else + { + g_key_file_remove_key(config, + sat_cfg_double[param].group, + sat_cfg_double[param].key, NULL); + } + + } + else + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s: Unknown double param index (%d)\n"), __func__, param); + } +} diff --git a/src/sat-cfg.h b/src/sat-cfg.h index 49d8b019..b40a5fc1 100644 --- a/src/sat-cfg.h +++ b/src/sat-cfg.h @@ -83,7 +83,6 @@ typedef enum { SAT_CFG_INT_MAP_GLOBAL_SHADOW_COL, /*!< Earth shadow colour. */ SAT_CFG_INT_MAP_TICK_COL, /*!< Tick labels colour. */ SAT_CFG_INT_MAP_TRACK_COL, /*!< Ground Track colour. */ - SAT_CFG_INT_MAP_TRACK_NUM, /*!< Number of orbits to show ground track for */ SAT_CFG_INT_MAP_SHADOW_ALPHA, /*!< Tranparency of shadow under satellite marker. */ SAT_CFG_INT_POLAR_REFRESH, /*!< Polar refresh rate (cycle). */ SAT_CFG_INT_POLAR_ORIENTATION, /*!< Orientation of the polar charts. */ @@ -155,6 +154,12 @@ typedef enum { SAT_CFG_STR_NUM /*!< Number of string parameters */ } sat_cfg_str_e; +/** Symbolic references for double config values. */ +typedef enum { + SAT_CFG_DOUBLE_MAP_TRACK_NUM, /*!< Number of orbits to show ground track for */ + SAT_CFG_DOUBLE_NUM +} sat_cfg_double_e; + guint sat_cfg_load(void); guint sat_cfg_save(void); void sat_cfg_close(void); @@ -170,5 +175,9 @@ gint sat_cfg_get_int(sat_cfg_int_e param); gint sat_cfg_get_int_def(sat_cfg_int_e param); void sat_cfg_set_int(sat_cfg_int_e param, gint value); void sat_cfg_reset_int(sat_cfg_int_e param); +gdouble sat_cfg_get_double(sat_cfg_double_e param); +gdouble sat_cfg_get_double_def(sat_cfg_double_e param); +void sat_cfg_set_double(sat_cfg_double_e param, gdouble value); +void sat_cfg_reset_double(sat_cfg_double_e param); #endif diff --git a/src/sat-pref-map-view.c b/src/sat-pref-map-view.c index c1230dd3..fcd161a9 100644 --- a/src/sat-pref-map-view.c +++ b/src/sat-pref-map-view.c @@ -93,10 +93,20 @@ static void colour_changed(GtkWidget * but, gpointer data) static void orbit_changed(GtkWidget * spin, gpointer data) { + gdouble value; + (void)spin; (void)data; dirty = TRUE; + + /* We allow fractional values <2 and integer values above. */ + value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(orbit)); + if (value >= 2.0) + { + /* Round to integer */ + gtk_spin_button_set_value(GTK_SPIN_BUTTON(orbit), (double)(int)value); + } } static void center_changed(GtkWidget * spin, gpointer data) @@ -255,8 +265,8 @@ static void reset_cb(GtkWidget * button, gpointer cfg) /* ground track orbits */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(orbit), - sat_cfg_get_int_def - (SAT_CFG_INT_MAP_TRACK_NUM)); + sat_cfg_get_double_def + (SAT_CFG_DOUBLE_MAP_TRACK_NUM)); /* center longitude */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(center), @@ -340,7 +350,7 @@ static void reset_cb(GtkWidget * button, gpointer cfg) /* ground track orbits */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(orbit), - sat_cfg_get_int(SAT_CFG_INT_MAP_TRACK_NUM)); + sat_cfg_get_double(SAT_CFG_DOUBLE_MAP_TRACK_NUM)); /* center longitude */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(center), @@ -469,10 +479,10 @@ void sat_pref_map_view_ok(GKeyFile * cfg) (GTK_TOGGLE_BUTTON(auto_ground_track))); /* orbit */ - g_key_file_set_integer(cfg, MOD_CFG_MAP_SECTION, - MOD_CFG_MAP_TRACK_NUM, - gtk_spin_button_get_value_as_int - (GTK_SPIN_BUTTON(orbit))); + g_key_file_set_double(cfg, MOD_CFG_MAP_SECTION, + MOD_CFG_MAP_TRACK_NUM, + gtk_spin_button_get_value + (GTK_SPIN_BUTTON(orbit))); /* map center */ g_key_file_set_integer(cfg, MOD_CFG_MAP_SECTION, @@ -557,9 +567,9 @@ void sat_pref_map_view_ok(GKeyFile * cfg) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (auto_ground_track))); /* orbit */ - sat_cfg_set_int(SAT_CFG_INT_MAP_TRACK_NUM, - gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON - (orbit))); + sat_cfg_set_double(SAT_CFG_DOUBLE_MAP_TRACK_NUM, + gtk_spin_button_get_value(GTK_SPIN_BUTTON + (orbit))); /* map center */ sat_cfg_set_int(SAT_CFG_INT_MAP_CENTER, @@ -657,7 +667,7 @@ void sat_pref_map_view_ok(GKeyFile * cfg) sat_cfg_reset_bool(SAT_CFG_BOOL_MAP_AUTO_GROUND_TRACK); /* orbit */ - sat_cfg_reset_int(SAT_CFG_INT_MAP_TRACK_NUM); + sat_cfg_reset_double(SAT_CFG_DOUBLE_MAP_TRACK_NUM); /* map center */ sat_cfg_reset_int(SAT_CFG_INT_MAP_CENTER); @@ -1274,7 +1284,7 @@ static void create_orbit_selector(GKeyFile * cfg, GtkBox * vbox) { GtkWidget *label; GtkWidget *hbox; - gint onum; + gdouble onum; hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE); @@ -1283,20 +1293,23 @@ static void create_orbit_selector(GKeyFile * cfg, GtkBox * vbox) label = gtk_label_new(_("Display ground track for")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - orbit = gtk_spin_button_new_with_range(1, 10, 1); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(orbit), 0); + orbit = gtk_spin_button_new_with_range(0.5, 10.0, 1.0); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(orbit), 1); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(orbit), TRUE); + gtk_widget_set_tooltip_text(orbit, + _("Value can be a fraction between 0.5-1.9 or an integer 2-10")); + if (cfg != NULL) { - onum = mod_cfg_get_int(cfg, - MOD_CFG_MAP_SECTION, - MOD_CFG_MAP_TRACK_NUM, - SAT_CFG_INT_MAP_TRACK_NUM); + onum = mod_cfg_get_double(cfg, + MOD_CFG_MAP_SECTION, + MOD_CFG_MAP_TRACK_NUM, + SAT_CFG_DOUBLE_MAP_TRACK_NUM); } else { - onum = sat_cfg_get_int(SAT_CFG_INT_MAP_TRACK_NUM); + onum = sat_cfg_get_double(SAT_CFG_DOUBLE_MAP_TRACK_NUM); } gtk_spin_button_set_value(GTK_SPIN_BUTTON(orbit), onum); g_signal_connect(G_OBJECT(orbit), "value-changed",