]> git.street.me.uk Git - andy/viking.git/blame - src/vikrouting.c
SF Features#116: Add an Acquire From URL option.
[andy/viking.git] / src / vikrouting.c
CommitLineData
9f30939a
GB
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 */
51static GList *routing_engine_list = NULL;
52
53static VikLayerParam prefs[] = {
a87f8fa1 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 },
9f30939a
GB
55};
56
57gchar **routing_engine_labels = NULL;
58gchar **routing_engine_ids = NULL;
59
60/**
61 * vik_routing_prefs_init:
62 *
63 * Initialize the preferences of the routing feature.
64 */
65void
66vik_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
e2905d92 75/* @see g_list_find_custom */
9f30939a
GB
76static gint
77search_by_id (gconstpointer a,
78 gconstpointer b)
79{
80 const gchar *id = b;
107570df 81 VikRoutingEngine *engine = (VikRoutingEngine *)a;
9f30939a
GB
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 */
95VikRoutingEngine *
96vik_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/**
5065b161 106 * vik_routing_default_engine:
9f30939a
GB
107 *
108 * Retrieve the default engine, based on user's preferences.
109 *
110 * Returns: the default engine
111 */
112static VikRoutingEngine *
5065b161 113vik_routing_default_engine ( void )
9f30939a 114{
107570df 115 const gchar *id = a_preferences_get ( VIKING_ROUTING_PARAMS_NAMESPACE "default")->s;
9f30939a
GB
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 */
129void
130vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end)
131{
132 /* The engine */
5065b161 133 VikRoutingEngine *engine = vik_routing_default_engine ( );
9f30939a
GB
134 /* The route computation */
135 vik_routing_engine_find ( engine, vt, start, end );
136}
137
138/**
139 * vik_routing_register:
140 * @engine: new routing engine to register
141 *
142 * Register a new routing engine.
143 */
144void
145vik_routing_register( VikRoutingEngine *engine )
146{
9f30939a
GB
147 gchar *label = vik_routing_engine_get_label ( engine );
148 gchar *id = vik_routing_engine_get_id ( engine );
9c98f76e 149 gsize len = 0;
9f30939a 150
9c98f76e
GB
151 /* check if id already exists in list */
152 GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id);
153 if (elem != NULL) {
154 g_debug("%s: %s already exists: update", __FUNCTION__, id);
9f30939a 155
9c98f76e
GB
156 /* Update main list */
157 g_object_unref (elem->data);
158 elem->data = g_object_ref ( engine );
159
160 /* Update GUI arrays */
161 len = g_strv_length (routing_engine_labels);
162 for (; len > 0 ; len--) {
163 if (strcmp (routing_engine_ids[len-1], id) == 0)
164 break;
165 }
166 /* Update the label (possibly different */
167 g_free (routing_engine_labels[len-1]);
168 routing_engine_labels[len-1] = g_strdup (label);
169
170 } else {
171 g_debug("%s: %s is new: append", __FUNCTION__, id);
172 routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) );
173
174 if (routing_engine_labels)
175 len = g_strv_length (routing_engine_labels);
176
177 /* Add the label */
178 routing_engine_labels = g_realloc (routing_engine_labels, (len+2)*sizeof(gchar*));
179 routing_engine_labels[len] = g_strdup (label);
180 routing_engine_labels[len+1] = NULL;
181
182 /* Add the id */
183 routing_engine_ids = g_realloc (routing_engine_ids, (len+2)*sizeof(gchar*));
184 routing_engine_ids[len] = g_strdup (id);
185 routing_engine_ids[len+1] = NULL;
9f30939a 186
9c98f76e
GB
187 /* Hack
188 We have to ensure the mode LayerParam references the up-to-date
189 GLists.
190 */
191 /*
192 memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
193 memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
194 */
195 prefs[0].widget_data = routing_engine_labels;
196 prefs[0].extra_widget_data = routing_engine_ids;
197 }
9f30939a
GB
198}
199
200/**
201 * vik_routing_unregister_all:
202 *
203 * Unregister all registered routing engines.
204 */
205void
206vik_routing_unregister_all ()
207{
208 g_list_foreach ( routing_engine_list, (GFunc) g_object_unref, NULL );
209 g_strfreev ( routing_engine_labels );
210 g_strfreev ( routing_engine_ids );
211}
0c59cc72
GB
212
213/**
214 * vik_routing_foreach_engine:
215 * @func: the function to run on each element
216 * @user_data: user's data to give to each call of @func
217 *
218 * Loop over all registered routing engines.
219 */
220void
221vik_routing_foreach_engine (GFunc func, gpointer user_data)
222{
223 g_list_foreach ( routing_engine_list, func, user_data );
224}
ed8f89f4
GB
225
226/*
227 * This function is called for all routing engine registered.
228 * Following result of the predicate function, the current engine
229 * is added to the combobox. In order to retrieve the VikRoutingEngine
230 * object, we store a list of added engine in a GObject's data "engines".
231 *
232 * @see g_list_foreach()
233 */
234static void
235fill_engine_box (gpointer data, gpointer user_data)
236{
237 VikRoutingEngine *engine = (VikRoutingEngine*) data;
238 /* Retrieve combo */
239 GtkWidget *widget = (GtkWidget*) user_data;
240
241 /* Only register engine fulliling expected behavior */
242 Predicate predicate = g_object_get_data ( G_OBJECT ( widget ), "func" );
243 gpointer predicate_data = g_object_get_data ( G_OBJECT ( widget ), "user_data" );
244 /* No predicate means to register all engines */
245 gboolean ok = predicate == NULL || predicate (engine, predicate_data);
246
247 if (ok)
248 {
249 /* Add item in widget */
250 const gchar *label = vik_routing_engine_get_label (engine);
251 vik_combo_box_text_append (widget, label);
252 /* Save engine in internal list */
253 GList *engines = (GList*) g_object_get_data ( G_OBJECT ( widget ) , "engines" );
254 engines = g_list_append ( engines, engine );
255 g_object_set_data ( G_OBJECT ( widget ), "engines", engines );
256 }
257}
258
259/**
260 * vik_routing_ui_selector_new:
261 * @func: user function to decide if an engine has to be added or not
262 * @user_data: user data for previous function
263 *
264 * Creates a combo box to allow selection of a routing engine.
265 *
266 * We use GObject data hastable to store and retrieve the VikRoutingEngine
267 * associated to the selection.
268 *
269 * Returns: the combo box
270 */
271GtkWidget *
272vik_routing_ui_selector_new (Predicate func, gpointer user_data)
273{
274 /* Create the combo */
275 GtkWidget * combo = vik_combo_box_text_new ();
276
277 /* Save data for foreach function */
278 g_object_set_data ( G_OBJECT ( combo ), "func", func );
279 g_object_set_data ( G_OBJECT ( combo ), "user_data", user_data );
280
281 /* Filter all engines with given user function */
282 vik_routing_foreach_engine (fill_engine_box, combo);
283
284 return combo;
285}
286
287/**
288 * vik_routing_ui_selector_get_nth:
289 * @combo: the GtkWidget combobox
290 * @pos: the selected position
291 *
292 * Retrieve the VikRoutingEngine stored in a list attached to @combo
293 * via the "engines" property.
294 *
295 * Returns: the VikRoutingEngine object associated to @pos
296 */
297VikRoutingEngine *
298vik_routing_ui_selector_get_nth (GtkWidget *combo, int pos)
299{
300 /* Retrieve engine */
301 GList *engines = (GList*) g_object_get_data ( G_OBJECT ( combo ) , "engines" );
302 VikRoutingEngine *engine = g_list_nth_data ( engines, pos );
303
304 return engine;
305}