2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2012-2013, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * @short_description: the routing framework
25 * This module handles the list of #VikRoutingEngine.
26 * It also handles the "default" functions.
34 #include <glib/gstdio.h>
35 #include <glib/gi18n.h>
37 #include "curl_download.h"
40 #include "preferences.h"
42 #include "vikrouting.h"
43 #include "vikroutingengine.h"
45 /* params will be routing.default */
46 /* we have to make sure these don't collide. */
47 #define VIKING_ROUTING_PARAMS_GROUP_KEY "routing"
48 #define VIKING_ROUTING_PARAMS_NAMESPACE "routing."
50 /* List to register all routing engines */
51 static GList *routing_engine_list = NULL;
53 static VikLayerParam prefs[] = {
54 { VIK_LAYER_NUM_TYPES, VIKING_ROUTING_PARAMS_NAMESPACE "default", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default engine:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL, NULL, NULL, NULL, NULL },
57 gchar **routing_engine_labels = NULL;
58 gchar **routing_engine_ids = NULL;
61 * vik_routing_prefs_init:
63 * Initialize the preferences of the routing feature.
66 vik_routing_prefs_init()
68 a_preferences_register_group ( VIKING_ROUTING_PARAMS_GROUP_KEY, _("Routing") );
70 VikLayerParamData tmp;
72 a_preferences_register(prefs, tmp, VIKING_ROUTING_PARAMS_GROUP_KEY);
75 /* @see g_list_find_custom */
77 search_by_id (gconstpointer a,
81 VikRoutingEngine *engine = (VikRoutingEngine *)a;
82 gchar *engineId = vik_routing_engine_get_id (engine);
84 return strcmp(id, engineId);
90 * vik_routing_find_engine:
91 * @id: the id of the engine we are looking for
93 * Returns: the found engine or %NULL
96 vik_routing_find_engine ( const gchar *id )
98 VikRoutingEngine *engine = NULL;
99 GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id);
106 * vik_routing_default_engine:
108 * Retrieve the default engine, based on user's preferences.
110 * Returns: the default engine
113 vik_routing_default_engine ( void )
115 const gchar *id = a_preferences_get ( VIKING_ROUTING_PARAMS_NAMESPACE "default")->s;
116 VikRoutingEngine *engine = vik_routing_find_engine(id);
117 if (engine == NULL && routing_engine_list != NULL && g_list_first (routing_engine_list) != NULL)
118 /* Fallback to first element */
119 engine = g_list_first (routing_engine_list)->data;
125 * vik_routing_default_find:
127 * Route computation with default engine.
129 * Return indicates success or not
132 vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end)
135 VikRoutingEngine *engine = vik_routing_default_engine ( );
136 /* The route computation */
137 return vik_routing_engine_find ( engine, vt, start, end );
141 * vik_routing_register:
142 * @engine: new routing engine to register
144 * Register a new routing engine.
147 vik_routing_register( VikRoutingEngine *engine )
149 gchar *label = vik_routing_engine_get_label ( engine );
150 gchar *id = vik_routing_engine_get_id ( engine );
153 /* check if id already exists in list */
154 GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id);
156 g_debug("%s: %s already exists: update", __FUNCTION__, id);
158 /* Update main list */
159 g_object_unref (elem->data);
160 elem->data = g_object_ref ( engine );
162 /* Update GUI arrays */
163 len = g_strv_length (routing_engine_labels);
164 for (; len > 0 ; len--) {
165 if (strcmp (routing_engine_ids[len-1], id) == 0)
168 /* Update the label (possibly different */
169 g_free (routing_engine_labels[len-1]);
170 routing_engine_labels[len-1] = g_strdup (label);
173 g_debug("%s: %s is new: append", __FUNCTION__, id);
174 routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) );
176 if (routing_engine_labels)
177 len = g_strv_length (routing_engine_labels);
180 routing_engine_labels = g_realloc (routing_engine_labels, (len+2)*sizeof(gchar*));
181 routing_engine_labels[len] = g_strdup (label);
182 routing_engine_labels[len+1] = NULL;
185 routing_engine_ids = g_realloc (routing_engine_ids, (len+2)*sizeof(gchar*));
186 routing_engine_ids[len] = g_strdup (id);
187 routing_engine_ids[len+1] = NULL;
190 We have to ensure the mode LayerParam references the up-to-date
194 memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer));
195 memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer));
197 prefs[0].widget_data = routing_engine_labels;
198 prefs[0].extra_widget_data = routing_engine_ids;
203 * vik_routing_unregister_all:
205 * Unregister all registered routing engines.
208 vik_routing_unregister_all ()
210 g_list_foreach ( routing_engine_list, (GFunc) g_object_unref, NULL );
211 g_strfreev ( routing_engine_labels );
212 g_strfreev ( routing_engine_ids );
216 * vik_routing_foreach_engine:
217 * @func: the function to run on each element
218 * @user_data: user's data to give to each call of @func
220 * Loop over all registered routing engines.
223 vik_routing_foreach_engine (GFunc func, gpointer user_data)
225 g_list_foreach ( routing_engine_list, func, user_data );
229 * This function is called for all routing engine registered.
230 * Following result of the predicate function, the current engine
231 * is added to the combobox. In order to retrieve the VikRoutingEngine
232 * object, we store a list of added engine in a GObject's data "engines".
234 * @see g_list_foreach()
237 fill_engine_box (gpointer data, gpointer user_data)
239 VikRoutingEngine *engine = (VikRoutingEngine*) data;
241 GtkWidget *widget = (GtkWidget*) user_data;
243 /* Only register engine fulfilling expected behaviour */
244 Predicate predicate = g_object_get_data ( G_OBJECT ( widget ), "func" );
245 gpointer predicate_data = g_object_get_data ( G_OBJECT ( widget ), "user_data" );
246 /* No predicate means to register all engines */
247 gboolean ok = predicate == NULL || predicate (engine, predicate_data);
251 /* Add item in widget */
252 const gchar *label = vik_routing_engine_get_label (engine);
253 vik_combo_box_text_append (widget, label);
254 /* Save engine in internal list */
255 GList *engines = (GList*) g_object_get_data ( G_OBJECT ( widget ) , "engines" );
256 engines = g_list_append ( engines, engine );
257 g_object_set_data ( G_OBJECT ( widget ), "engines", engines );
262 * vik_routing_ui_selector_new:
263 * @func: user function to decide if an engine has to be added or not
264 * @user_data: user data for previous function
266 * Creates a combo box to allow selection of a routing engine.
268 * We use GObject data hashtable to store and retrieve the VikRoutingEngine
269 * associated to the selection.
271 * Returns: the combo box
274 vik_routing_ui_selector_new (Predicate func, gpointer user_data)
276 /* Create the combo */
277 GtkWidget * combo = vik_combo_box_text_new ();
279 /* Save data for foreach function */
280 g_object_set_data ( G_OBJECT ( combo ), "func", func );
281 g_object_set_data ( G_OBJECT ( combo ), "user_data", user_data );
283 /* Filter all engines with given user function */
284 vik_routing_foreach_engine (fill_engine_box, combo);
290 * vik_routing_ui_selector_get_nth:
291 * @combo: the GtkWidget combobox
292 * @pos: the selected position
294 * Retrieve the VikRoutingEngine stored in a list attached to @combo
295 * via the "engines" property.
297 * Returns: the VikRoutingEngine object associated to @pos
300 vik_routing_ui_selector_get_nth (GtkWidget *combo, int pos)
302 /* Retrieve engine */
303 GList *engines = (GList*) g_object_get_data ( G_OBJECT ( combo ) , "engines" );
304 VikRoutingEngine *engine = g_list_nth_data ( engines, pos );
309 // For simplicity a variable with visibility to multiple functions
310 static guint engine_count = 0;
313 count_engine_directions (gpointer data, gpointer user_data)
315 VikRoutingEngine *engine = (VikRoutingEngine*) data;
316 if ( vik_routing_engine_supports_direction ( engine ) )
321 * vik_routing_number_of_engines:
323 * Returns: the number of engines available
325 guint vik_routing_number_of_engines ( VikRoutingMethodType method )
328 if ( routing_engine_list ) {
329 if ( method == VIK_ROUTING_METHOD_DIRECTIONS )
330 vik_routing_foreach_engine ( count_engine_directions, NULL );
332 // ATM Every engine supports Lat/Lon requests
333 engine_count = g_list_length ( routing_engine_list );