]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikrouting.c
Improve place search failure message to say if it is a service level issue.
[andy/viking.git] / src / vikrouting.c
index 6a4fd4771ac52596b4d6994786e12414b9ef91ec..1192cdab5e4ef4c6d7d0e868f9d79f6b7f9967e7 100644 (file)
@@ -51,7 +51,7 @@
 static GList *routing_engine_list = NULL;
 
 static VikLayerParam prefs[] = {
-  { 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 },
+  { 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 },
 };
 
 gchar **routing_engine_labels = NULL;
@@ -65,19 +65,20 @@ gchar **routing_engine_ids = NULL;
 void
 vik_routing_prefs_init()
 {
-  a_preferences_register_group ( VIKING_ROUTING_PARAMS_GROUP_KEY, "Routing" );
+  a_preferences_register_group ( VIKING_ROUTING_PARAMS_GROUP_KEY, _("Routing") );
 
   VikLayerParamData tmp;
   tmp.s = NULL;
   a_preferences_register(prefs, tmp, VIKING_ROUTING_PARAMS_GROUP_KEY);
 }
 
+/* @see g_list_find_custom */
 static gint
 search_by_id (gconstpointer a,
               gconstpointer b)
 {
        const gchar *id = b;
-       VikRoutingEngine *engine = a;
+       VikRoutingEngine *engine = (VikRoutingEngine *)a;
        gchar *engineId = vik_routing_engine_get_id (engine);
        if (id && engine)
                return strcmp(id, engineId);
@@ -102,16 +103,16 @@ vik_routing_find_engine ( const gchar *id )
 }
 
 /**
- * vik_routing_default:
+ * vik_routing_default_engine:
  * 
  * Retrieve the default engine, based on user's preferences.
  * 
  * Returns: the default engine
  */
-static VikRoutingEngine *
-vik_routing_default( void )
+VikRoutingEngine *
+vik_routing_default_engine ( void )
 {
-  gchar *id = a_preferences_get ( VIKING_ROUTING_PARAMS_NAMESPACE "default")->s;
+  const gchar *id = a_preferences_get ( VIKING_ROUTING_PARAMS_NAMESPACE "default")->s;
   VikRoutingEngine *engine = vik_routing_find_engine(id);
   if (engine == NULL && routing_engine_list != NULL && g_list_first (routing_engine_list) != NULL)
     /* Fallback to first element */
@@ -124,14 +125,16 @@ vik_routing_default( void )
  * vik_routing_default_find:
  * 
  * Route computation with default engine.
+ *
+ * Return indicates success or not
  */
-void
+gboolean
 vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end)
 {
   /* The engine */
-  VikRoutingEngine *engine = vik_routing_default ( );
+  VikRoutingEngine *engine = vik_routing_default_engine ( );
   /* The route computation */
-  vik_routing_engine_find ( engine, vt, start, end );
+  return vik_routing_engine_find ( engine, vt, start, end );
 }
 
 /**
@@ -143,36 +146,57 @@ vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end
 void
 vik_routing_register( VikRoutingEngine *engine )
 {
-  if ( VIK_IS_ROUTING_ENGINE ( engine ) )
-    routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) );
-
-  gsize len = 0;
-  if (routing_engine_labels)
-    len = g_strv_length (routing_engine_labels);
-
   gchar *label = vik_routing_engine_get_label ( engine );
   gchar *id = vik_routing_engine_get_id ( engine );
+  gsize len = 0;
+
+  /* check if id already exists in list */
+  GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id);
+  if (elem != NULL) {
+    g_debug("%s: %s already exists: update", __FUNCTION__, id);
+
+    /* Update main list */
+    g_object_unref (elem->data);
+    elem->data = g_object_ref ( engine );
+
+    /* Update GUI arrays */
+    len = g_strv_length (routing_engine_labels);
+    for (; len > 0 ; len--) {
+      if (strcmp (routing_engine_ids[len-1], id) == 0)
+                       break;
+       }
+    /* Update the label (possibly different */
+    g_free (routing_engine_labels[len-1]);
+    routing_engine_labels[len-1] = g_strdup (label);
+    
+  } else {
+    g_debug("%s: %s is new: append", __FUNCTION__, id);
+    routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) );
 
-  /* Add the label */
-  routing_engine_labels = g_realloc (routing_engine_labels, (len+2)*sizeof(gchar*));
-  routing_engine_labels[len] = g_strdup (label);
-  routing_engine_labels[len+1] = NULL;
+    if (routing_engine_labels)
+      len = g_strv_length (routing_engine_labels);
+  
+    /* Add the label */
+    routing_engine_labels = g_realloc (routing_engine_labels, (len+2)*sizeof(gchar*));
+    routing_engine_labels[len] = g_strdup (label);
+    routing_engine_labels[len+1] = NULL;
 
-  /* Add the id */
-  routing_engine_ids = g_realloc (routing_engine_ids, (len+2)*sizeof(gchar*));
-  routing_engine_ids[len] = g_strdup (id);
-  routing_engine_ids[len+1] = NULL;
+    /* Add the id */
+    routing_engine_ids = g_realloc (routing_engine_ids, (len+2)*sizeof(gchar*));
+    routing_engine_ids[len] = g_strdup (id);
+    routing_engine_ids[len+1] = NULL;
   
-  /* Hack
-     We have to ensure the mode LayerParam references the up-to-date
-     GLists.
-  */
-  /*
-  memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
-  memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
-  */
-  prefs[0].widget_data = routing_engine_labels;
-  prefs[0].extra_widget_data = routing_engine_ids;
+    /* Hack
+       We have to ensure the mode LayerParam references the up-to-date
+       GLists.
+    */
+    /*
+    memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
+    memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
+    */
+    prefs[0].widget_data = routing_engine_labels;
+    prefs[0].extra_widget_data = routing_engine_ids;
+  }
 }
 
 /**
@@ -187,3 +211,97 @@ vik_routing_unregister_all ()
   g_strfreev ( routing_engine_labels );
   g_strfreev ( routing_engine_ids );
 }
+
+/**
+ * vik_routing_foreach_engine:
+ * @func: the function to run on each element
+ * @user_data: user's data to give to each call of @func
+ *
+ * Loop over all registered routing engines.
+ */
+void
+vik_routing_foreach_engine (GFunc func, gpointer user_data)
+{
+  g_list_foreach ( routing_engine_list, func, user_data );
+}
+
+/*
+ * This function is called for all routing engine registered.
+ * Following result of the predicate function, the current engine
+ * is added to the combobox. In order to retrieve the VikRoutingEngine
+ * object, we store a list of added engine in a GObject's data "engines".
+ *
+ * @see g_list_foreach()
+ */
+static void
+fill_engine_box (gpointer data, gpointer user_data)
+{
+  VikRoutingEngine *engine = (VikRoutingEngine*) data;
+  /* Retrieve combo */
+  GtkWidget *widget = (GtkWidget*) user_data;
+
+  /* Only register engine fulliling expected behavior */
+  Predicate predicate = g_object_get_data ( G_OBJECT ( widget ), "func" );
+  gpointer predicate_data = g_object_get_data ( G_OBJECT ( widget ), "user_data" );
+  /* No predicate means to register all engines */
+  gboolean ok = predicate == NULL || predicate (engine, predicate_data);
+
+  if (ok)
+  {
+    /* Add item in widget */
+    const gchar *label = vik_routing_engine_get_label (engine);
+    vik_combo_box_text_append (widget, label);
+    /* Save engine in internal list */
+    GList *engines = (GList*) g_object_get_data ( G_OBJECT ( widget ) , "engines" );
+    engines = g_list_append ( engines, engine );
+    g_object_set_data ( G_OBJECT ( widget ), "engines", engines );
+  }
+}
+
+/**
+ * vik_routing_ui_selector_new:
+ * @func: user function to decide if an engine has to be added or not
+ * @user_data: user data for previous function
+ *
+ * Creates a combo box to allow selection of a routing engine.
+ *
+ * We use GObject data hastable to store and retrieve the VikRoutingEngine
+ * associated to the selection.
+ *
+ * Returns: the combo box
+ */
+GtkWidget *
+vik_routing_ui_selector_new (Predicate func, gpointer user_data)
+{
+  /* Create the combo */
+  GtkWidget * combo = vik_combo_box_text_new ();
+
+  /* Save data for foreach function */
+  g_object_set_data ( G_OBJECT ( combo ), "func", func );
+  g_object_set_data ( G_OBJECT ( combo ), "user_data", user_data );
+
+  /* Filter all engines with given user function */
+  vik_routing_foreach_engine (fill_engine_box, combo);
+
+  return combo;
+}
+
+/**
+ * vik_routing_ui_selector_get_nth:
+ * @combo: the GtkWidget combobox
+ * @pos: the selected position
+ *
+ * Retrieve the VikRoutingEngine stored in a list attached to @combo
+ * via the "engines" property.
+ *
+ * Returns: the VikRoutingEngine object associated to @pos
+ */
+VikRoutingEngine *
+vik_routing_ui_selector_get_nth (GtkWidget *combo, int pos)
+{
+  /* Retrieve engine */
+  GList *engines = (GList*) g_object_get_data ( G_OBJECT ( combo ) , "engines" );
+  VikRoutingEngine *engine = g_list_nth_data ( engines, pos );
+
+  return engine;
+}