]> git.street.me.uk Git - andy/viking.git/blob - src/vikrouting.c
Read zip files contents which are stored with no compression.
[andy/viking.git] / src / vikrouting.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2012-2013, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 /**
22  * SECTION:vikrouting
23  * @short_description: the routing framework
24  * 
25  * This module handles the list of #VikRoutingEngine.
26  * It also handles the "default" functions.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <glib.h>
34 #include <glib/gstdio.h>
35 #include <glib/gi18n.h>
36
37 #include "curl_download.h"
38 #include "babel.h"
39
40 #include "preferences.h"
41
42 #include "vikrouting.h"
43 #include "vikroutingengine.h"
44
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."
49
50 /* List to register all routing engines */
51 static GList *routing_engine_list = NULL;
52
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 },
55 };
56
57 gchar **routing_engine_labels = NULL;
58 gchar **routing_engine_ids = NULL;
59
60 /**
61  * vik_routing_prefs_init:
62  * 
63  * Initialize the preferences of the routing feature.
64  */
65 void
66 vik_routing_prefs_init()
67 {
68   a_preferences_register_group ( VIKING_ROUTING_PARAMS_GROUP_KEY, _("Routing") );
69
70   VikLayerParamData tmp;
71   tmp.s = NULL;
72   a_preferences_register(prefs, tmp, VIKING_ROUTING_PARAMS_GROUP_KEY);
73 }
74
75 /* @see g_list_find_custom */
76 static gint
77 search_by_id (gconstpointer a,
78               gconstpointer b)
79 {
80         const gchar *id = b;
81         VikRoutingEngine *engine = (VikRoutingEngine *)a;
82         gchar *engineId = vik_routing_engine_get_id (engine);
83         if (id && engine)
84                 return strcmp(id, engineId);
85         else
86                 return -1;
87 }
88
89 /**
90  * vik_routing_find_engine:
91  * @id: the id of the engine we are looking for
92  * 
93  * Returns: the found engine or %NULL
94  */
95 VikRoutingEngine *
96 vik_routing_find_engine ( const gchar *id )
97 {
98         VikRoutingEngine *engine = NULL;
99         GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id);
100         if (elem)
101                 engine = elem->data;
102         return engine;
103 }
104
105 /**
106  * vik_routing_default_engine:
107  * 
108  * Retrieve the default engine, based on user's preferences.
109  * 
110  * Returns: the default engine
111  */
112 VikRoutingEngine *
113 vik_routing_default_engine ( void )
114 {
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;
120
121   return engine;
122 }
123
124 /**
125  * vik_routing_default_find:
126  * 
127  * Route computation with default engine.
128  *
129  * Return indicates success or not
130  */
131 gboolean
132 vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end)
133 {
134   /* The engine */
135   VikRoutingEngine *engine = vik_routing_default_engine ( );
136   /* The route computation */
137   return vik_routing_engine_find ( engine, vt, start, end );
138 }
139
140 /**
141  * vik_routing_register:
142  * @engine: new routing engine to register
143  * 
144  * Register a new routing engine.
145  */
146 void
147 vik_routing_register( VikRoutingEngine *engine )
148 {
149   gchar *label = vik_routing_engine_get_label ( engine );
150   gchar *id = vik_routing_engine_get_id ( engine );
151   gsize len = 0;
152
153   /* check if id already exists in list */
154   GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id);
155   if (elem != NULL) {
156     g_debug("%s: %s already exists: update", __FUNCTION__, id);
157
158     /* Update main list */
159     g_object_unref (elem->data);
160     elem->data = g_object_ref ( engine );
161
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)
166                         break;
167         }
168     /* Update the label (possibly different */
169     g_free (routing_engine_labels[len-1]);
170     routing_engine_labels[len-1] = g_strdup (label);
171     
172   } else {
173     g_debug("%s: %s is new: append", __FUNCTION__, id);
174     routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) );
175
176     if (routing_engine_labels)
177       len = g_strv_length (routing_engine_labels);
178   
179     /* Add the label */
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;
183
184     /* Add the id */
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;
188   
189     /* Hack
190        We have to ensure the mode LayerParam references the up-to-date
191        GLists.
192     */
193     /*
194     memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
195     memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
196     */
197     prefs[0].widget_data = routing_engine_labels;
198     prefs[0].extra_widget_data = routing_engine_ids;
199   }
200 }
201
202 /**
203  * vik_routing_unregister_all:
204  * 
205  * Unregister all registered routing engines.
206  */
207 void
208 vik_routing_unregister_all ()
209 {
210   g_list_foreach ( routing_engine_list, (GFunc) g_object_unref, NULL );
211   g_strfreev ( routing_engine_labels );
212   g_strfreev ( routing_engine_ids );
213 }
214
215 /**
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
219  *
220  * Loop over all registered routing engines.
221  */
222 void
223 vik_routing_foreach_engine (GFunc func, gpointer user_data)
224 {
225   g_list_foreach ( routing_engine_list, func, user_data );
226 }
227
228 /*
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".
233  *
234  * @see g_list_foreach()
235  */
236 static void
237 fill_engine_box (gpointer data, gpointer user_data)
238 {
239   VikRoutingEngine *engine = (VikRoutingEngine*) data;
240   /* Retrieve combo */
241   GtkWidget *widget = (GtkWidget*) user_data;
242
243   /* Only register engine fulliling expected behavior */
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);
248
249   if (ok)
250   {
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 );
258   }
259 }
260
261 /**
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
265  *
266  * Creates a combo box to allow selection of a routing engine.
267  *
268  * We use GObject data hastable to store and retrieve the VikRoutingEngine
269  * associated to the selection.
270  *
271  * Returns: the combo box
272  */
273 GtkWidget *
274 vik_routing_ui_selector_new (Predicate func, gpointer user_data)
275 {
276   /* Create the combo */
277   GtkWidget * combo = vik_combo_box_text_new ();
278
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 );
282
283   /* Filter all engines with given user function */
284   vik_routing_foreach_engine (fill_engine_box, combo);
285
286   return combo;
287 }
288
289 /**
290  * vik_routing_ui_selector_get_nth:
291  * @combo: the GtkWidget combobox
292  * @pos: the selected position
293  *
294  * Retrieve the VikRoutingEngine stored in a list attached to @combo
295  * via the "engines" property.
296  *
297  * Returns: the VikRoutingEngine object associated to @pos
298  */
299 VikRoutingEngine *
300 vik_routing_ui_selector_get_nth (GtkWidget *combo, int pos)
301 {
302   /* Retrieve engine */
303   GList *engines = (GList*) g_object_get_data ( G_OBJECT ( combo ) , "engines" );
304   VikRoutingEngine *engine = g_list_nth_data ( engines, pos );
305
306   return engine;
307 }