]>
Commit | Line | Data |
---|---|---|
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 }, | |
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 | static 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 | void | |
130 | vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end) | |
131 | { | |
132 | /* The engine */ | |
133 | VikRoutingEngine *engine = vik_routing_default_engine ( ); | |
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 | */ | |
144 | void | |
145 | vik_routing_register( VikRoutingEngine *engine ) | |
146 | { | |
147 | gchar *label = vik_routing_engine_get_label ( engine ); | |
148 | gchar *id = vik_routing_engine_get_id ( engine ); | |
149 | gsize len = 0; | |
150 | ||
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); | |
155 | ||
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; | |
186 | ||
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, ¶ms_maptypes, sizeof(gpointer)); | |
193 | memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer)); | |
194 | */ | |
195 | prefs[0].widget_data = routing_engine_labels; | |
196 | prefs[0].extra_widget_data = routing_engine_ids; | |
197 | } | |
198 | } | |
199 | ||
200 | /** | |
201 | * vik_routing_unregister_all: | |
202 | * | |
203 | * Unregister all registered routing engines. | |
204 | */ | |
205 | void | |
206 | vik_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 | } | |
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 | */ | |
220 | void | |
221 | vik_routing_foreach_engine (GFunc func, gpointer user_data) | |
222 | { | |
223 | g_list_foreach ( routing_engine_list, func, user_data ); | |
224 | } | |
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 | */ | |
234 | static void | |
235 | fill_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 | */ | |
271 | GtkWidget * | |
272 | vik_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 | */ | |
297 | VikRoutingEngine * | |
298 | vik_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 | } |