X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/9f30939ade46329639cb8586a6cc1e29a9a495b1..6339640601c48c559aed48a573946fc25785a6e9:/src/vikrouting.c?ds=sidebyside diff --git a/src/vikrouting.c b/src/vikrouting.c index 6a4fd477..45981cba 100644 --- a/src/vikrouting.c +++ b/src/vikrouting.c @@ -72,12 +72,13 @@ vik_routing_prefs_init() a_preferences_register(prefs, tmp, VIKING_ROUTING_PARAMS_GROUP_KEY); } +/* @see g_list_find_custom */ static gint search_by_id (gconstpointer a, gconstpointer b) { const gchar *id = b; - VikRoutingEngine *engine = a; + VikRoutingEngine *engine = (VikRoutingEngine *)a; gchar *engineId = vik_routing_engine_get_id (engine); if (id && engine) return strcmp(id, engineId); @@ -102,16 +103,16 @@ vik_routing_find_engine ( const gchar *id ) } /** - * vik_routing_default: + * vik_routing_default_engine: * * Retrieve the default engine, based on user's preferences. * * Returns: the default engine */ static VikRoutingEngine * -vik_routing_default( void ) +vik_routing_default_engine ( void ) { - gchar *id = a_preferences_get ( VIKING_ROUTING_PARAMS_NAMESPACE "default")->s; + const gchar *id = a_preferences_get ( VIKING_ROUTING_PARAMS_NAMESPACE "default")->s; VikRoutingEngine *engine = vik_routing_find_engine(id); if (engine == NULL && routing_engine_list != NULL && g_list_first (routing_engine_list) != NULL) /* Fallback to first element */ @@ -129,7 +130,7 @@ void vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end) { /* The engine */ - VikRoutingEngine *engine = vik_routing_default ( ); + VikRoutingEngine *engine = vik_routing_default_engine ( ); /* The route computation */ vik_routing_engine_find ( engine, vt, start, end ); } @@ -143,36 +144,57 @@ vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end void vik_routing_register( VikRoutingEngine *engine ) { - if ( VIK_IS_ROUTING_ENGINE ( engine ) ) - routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) ); - - gsize len = 0; - if (routing_engine_labels) - len = g_strv_length (routing_engine_labels); - gchar *label = vik_routing_engine_get_label ( engine ); gchar *id = vik_routing_engine_get_id ( engine ); + gsize len = 0; - /* Add the label */ - routing_engine_labels = g_realloc (routing_engine_labels, (len+2)*sizeof(gchar*)); - routing_engine_labels[len] = g_strdup (label); - routing_engine_labels[len+1] = NULL; + /* check if id already exists in list */ + GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id); + if (elem != NULL) { + g_debug("%s: %s already exists: update", __FUNCTION__, id); + + /* Update main list */ + g_object_unref (elem->data); + elem->data = g_object_ref ( engine ); + + /* Update GUI arrays */ + len = g_strv_length (routing_engine_labels); + for (; len > 0 ; len--) { + if (strcmp (routing_engine_ids[len-1], id) == 0) + break; + } + /* Update the label (possibly different */ + g_free (routing_engine_labels[len-1]); + routing_engine_labels[len-1] = g_strdup (label); + + } else { + g_debug("%s: %s is new: append", __FUNCTION__, id); + routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) ); + + if (routing_engine_labels) + len = g_strv_length (routing_engine_labels); + + /* Add the label */ + routing_engine_labels = g_realloc (routing_engine_labels, (len+2)*sizeof(gchar*)); + routing_engine_labels[len] = g_strdup (label); + routing_engine_labels[len+1] = NULL; - /* Add the id */ - routing_engine_ids = g_realloc (routing_engine_ids, (len+2)*sizeof(gchar*)); - routing_engine_ids[len] = g_strdup (id); - routing_engine_ids[len+1] = NULL; + /* Add the id */ + routing_engine_ids = g_realloc (routing_engine_ids, (len+2)*sizeof(gchar*)); + routing_engine_ids[len] = g_strdup (id); + routing_engine_ids[len+1] = NULL; - /* Hack - We have to ensure the mode LayerParam references the up-to-date - GLists. - */ - /* - memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer)); - memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer)); - */ - prefs[0].widget_data = routing_engine_labels; - prefs[0].extra_widget_data = routing_engine_ids; + /* Hack + We have to ensure the mode LayerParam references the up-to-date + GLists. + */ + /* + memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer)); + memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer)); + */ + prefs[0].widget_data = routing_engine_labels; + prefs[0].extra_widget_data = routing_engine_ids; + } } /** @@ -187,3 +209,97 @@ vik_routing_unregister_all () g_strfreev ( routing_engine_labels ); g_strfreev ( routing_engine_ids ); } + +/** + * vik_routing_foreach_engine: + * @func: the function to run on each element + * @user_data: user's data to give to each call of @func + * + * Loop over all registered routing engines. + */ +void +vik_routing_foreach_engine (GFunc func, gpointer user_data) +{ + g_list_foreach ( routing_engine_list, func, user_data ); +} + +/* + * This function is called for all routing engine registered. + * Following result of the predicate function, the current engine + * is added to the combobox. In order to retrieve the VikRoutingEngine + * object, we store a list of added engine in a GObject's data "engines". + * + * @see g_list_foreach() + */ +static void +fill_engine_box (gpointer data, gpointer user_data) +{ + VikRoutingEngine *engine = (VikRoutingEngine*) data; + /* Retrieve combo */ + GtkWidget *widget = (GtkWidget*) user_data; + + /* Only register engine fulliling expected behavior */ + Predicate predicate = g_object_get_data ( G_OBJECT ( widget ), "func" ); + gpointer predicate_data = g_object_get_data ( G_OBJECT ( widget ), "user_data" ); + /* No predicate means to register all engines */ + gboolean ok = predicate == NULL || predicate (engine, predicate_data); + + if (ok) + { + /* Add item in widget */ + const gchar *label = vik_routing_engine_get_label (engine); + vik_combo_box_text_append (widget, label); + /* Save engine in internal list */ + GList *engines = (GList*) g_object_get_data ( G_OBJECT ( widget ) , "engines" ); + engines = g_list_append ( engines, engine ); + g_object_set_data ( G_OBJECT ( widget ), "engines", engines ); + } +} + +/** + * vik_routing_ui_selector_new: + * @func: user function to decide if an engine has to be added or not + * @user_data: user data for previous function + * + * Creates a combo box to allow selection of a routing engine. + * + * We use GObject data hastable to store and retrieve the VikRoutingEngine + * associated to the selection. + * + * Returns: the combo box + */ +GtkWidget * +vik_routing_ui_selector_new (Predicate func, gpointer user_data) +{ + /* Create the combo */ + GtkWidget * combo = vik_combo_box_text_new (); + + /* Save data for foreach function */ + g_object_set_data ( G_OBJECT ( combo ), "func", func ); + g_object_set_data ( G_OBJECT ( combo ), "user_data", user_data ); + + /* Filter all engines with given user function */ + vik_routing_foreach_engine (fill_engine_box, combo); + + return combo; +} + +/** + * vik_routing_ui_selector_get_nth: + * @combo: the GtkWidget combobox + * @pos: the selected position + * + * Retrieve the VikRoutingEngine stored in a list attached to @combo + * via the "engines" property. + * + * Returns: the VikRoutingEngine object associated to @pos + */ +VikRoutingEngine * +vik_routing_ui_selector_get_nth (GtkWidget *combo, int pos) +{ + /* Retrieve engine */ + GList *engines = (GList*) g_object_get_data ( G_OBJECT ( combo ) , "engines" ); + VikRoutingEngine *engine = g_list_nth_data ( engines, pos ); + + return engine; +}