]>
Commit | Line | Data |
---|---|---|
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 */ | |
51 | static GList *routing_engine_list = NULL; | |
52 | ||
53 | static VikLayerParam prefs[] = { | |
63959706 | 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 }, |
9f30939a GB |
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 | ||
e2905d92 | 75 | /* @see g_list_find_custom */ |
9f30939a GB |
76 | static gint |
77 | search_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 | */ | |
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 | /** | |
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 | */ | |
8b54a48f | 112 | VikRoutingEngine * |
5065b161 | 113 | vik_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. | |
8b54a48f MH |
128 | * |
129 | * Return indicates success or not | |
9f30939a | 130 | */ |
8b54a48f | 131 | gboolean |
9f30939a GB |
132 | vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end) |
133 | { | |
134 | /* The engine */ | |
5065b161 | 135 | VikRoutingEngine *engine = vik_routing_default_engine ( ); |
9f30939a | 136 | /* The route computation */ |
41e48655 | 137 | return vik_routing_engine_find ( engine, vt, start, end ); |
9f30939a GB |
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 | { | |
9f30939a GB |
149 | gchar *label = vik_routing_engine_get_label ( engine ); |
150 | gchar *id = vik_routing_engine_get_id ( engine ); | |
9c98f76e | 151 | gsize len = 0; |
9f30939a | 152 | |
9c98f76e GB |
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); | |
9f30939a | 157 | |
9c98f76e GB |
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; | |
9f30939a | 188 | |
9c98f76e GB |
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, ¶ms_maptypes, sizeof(gpointer)); | |
195 | memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer)); | |
196 | */ | |
197 | prefs[0].widget_data = routing_engine_labels; | |
198 | prefs[0].extra_widget_data = routing_engine_ids; | |
199 | } | |
9f30939a GB |
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 | } | |
0c59cc72 GB |
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 | } | |
ed8f89f4 GB |
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 | } |