]> err.no Git - mapper/commitdiff
Combine extra functions from old track.* and route.*
authorKaj-Michael Lang <milang@tal.org>
Wed, 11 Jun 2008 15:13:41 +0000 (18:13 +0300)
committerKaj-Michael Lang <milang@tal.org>
Wed, 11 Jun 2008 15:13:41 +0000 (18:13 +0300)
src/route.h
src/track.c
src/track.h

index b45031c05854dd730ab91fcea2c099f55a903eb7..cdb81eff7e6cce1152073e04834287f5694e729f 100644 (file)
@@ -33,7 +33,6 @@ gboolean route_download(Path *route, gchar *to);
 gboolean route_clear(Path *route);
 
 void route_check_waypoint_announce(Path *route, GpsData *gps);
-void route_autoroute_check(Path *route);
 
 gboolean route_auto_route_dl_idle_cb();
 void route_cancel_autoroute(Path *route, gboolean temporary);
index 49d5abc33ecbaceb27caebbbb36121b2391cece8..c6e9ca2583886436eae3b82c58616e50c725fabd 100644 (file)
 #include "latlon.h"
 #include "path.h"
 
-/* Add sensitivity */
-static gint sensitivity=3;
+typedef struct _OriginToggleInfo OriginToggleInfo;
+struct _OriginToggleInfo {
+       GtkWidget *rad_use_gps;
+       GtkWidget *rad_use_route;
+       GtkWidget *rad_use_text;
+       GtkWidget *chk_auto;
+       GtkWidget *txt_from;
+       GtkWidget *txt_to;
+       Path *path;
+};
 
-void 
-track_clear(Path *track)
+/**
+ * path_clear_ask:
+ * @path
+ * @msg
+ *
+ * Ask confirmation to clear given path, using msg as the question.
+ *
+ * Returns: TRUE if path was cleared.
+ */
+gboolean
+path_clear_ask(Path *path, const gchar *msg)
 {
 GtkWidget *confirm;
+gboolean res=FALSE;
 
-confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), _("Clear the track?"));
+g_return_val_if_fail(path, FALSE);
 
+confirm=hildon_note_new_confirmation(GTK_WINDOW(_window), msg);
 if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) {
-       path_clear(track);
-       map_force_redraw();
+       path_clear(path);
+       res=TRUE;
 }
 gtk_widget_destroy(confirm);
-}
-
-gdouble
-track_calculate_distance_from(Point *point)
-{
-Point *curr;
-gdouble lat1, lon1, lat2, lon2;
-gdouble sum = 0.0;
-
-unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1);
-
-/* Skip _track->tail because that should be _gps. */
-for (curr = _track->tail; curr > point; --curr) {
-       if (curr->unity) {
-               unit2latlon(curr->unitx, curr->unity, lat2, lon2);
-               sum += calculate_distance(lat1, lon1, lat2, lon2);
-               lat1 = lat2;
-               lon1 = lon2;
-       }
-}
-return sum;
+return res;
 }
 
 void 
-track_show_distance_from(Point *point)
+track_show_distance_from(Path *path, Point *point)
 {
 gchar buffer[80];
 gdouble sum;
 
-sum = track_calculate_distance_from(point);
+sum=path_calculate_distance_from(path, point);
 g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
 MACRO_BANNER_SHOW_INFO(_window, buffer);
 }
 
 void 
-track_show_distance_from_last()
+track_show_distance_from_last(Path *track)
 {
 /* Find last zero point. */
-if (_track->head != _track->tail) {
+if (track->head != track->tail) {
        Point *point;
        /* Find last zero point. */
        for (point = _track->tail; point->unity; point--) {
@@ -80,90 +79,448 @@ if (_track->head != _track->tail) {
 }
 
 void 
-track_show_distance_from_first()
+track_show_distance_from_first(Path *track)
 {
-if (_track->head != _track->tail) {
-       track_show_distance_from(_track->head);
+if (track->head != track->tail) {
+       track_show_distance_from(track->head);
 } else {
        MACRO_BANNER_SHOW_INFO(_window, _("The current track is empty."));
 }
 }
 
 /**
- * Add a point to the _track list.
- *
- * If a non-null gps is given, then the current position is appended 
- * to _track with the given time.  If gps is null, then _point_null is 
- * appended to _track with time zero (this produces a "break" in the track).
+ * Check if we should re-calculate route
+ */
+void
+route_autoroute_check(Path *route)
+{
+g_return_if_fail(route);
+
+if (_autoroute_data.enabled && !_autoroute_data.in_progress && route->near_point_dist_squared > 400) {
+       MACRO_BANNER_SHOW_INFO(_window, _("Recalculating directions..."));
+       _autoroute_data.in_progress = TRUE;
+       show_directions = FALSE;
+       g_idle_add((GSourceFunc)route_auto_route_dl_idle_cb, NULL);
+}
+}
+
+gboolean 
+route_open_file(Path *route)
+{
+gchar *buffer;
+gint size;
+
+g_return_val_if_fail(route, FALSE);
+
+if (file_open_get_contents(&_route_dir_uri, &buffer, &size)) {
+       /* If auto is enabled, append the route, otherwise replace it. */
+       if (path_gpx_parse(route, buffer, size, _autoroute_data.enabled ? GPX_PATH_APPEND : GPX_PATH_NEW)) {
+               route_cancel_autoroute(route, FALSE);
+
+               MACRO_BANNER_SHOW_INFO(_window, _("Route Opened"));
+               /* Find the nearest route point, if we're connected. */
+               path_find_nearest_point(route);
+               route_set_destination_from_last(route, &_dest);
+               return TRUE;
+       } else {
+               popup_error(_window, _("Error parsing GPX file."));
+               g_free(buffer);
+               return FALSE;
+       }
+}
+return FALSE;
+}
+
+/**
+ * Ask user to save route
  */
 gboolean
-track_add(Path *track, GpsData *gps)
+route_save(Path *route)
 {
-if (!gps) {
-       MACRO_PATH_INCREMENT_TAIL(*track);
-       *track->tail=_point_null;
+GnomeVFSHandle *handle;
+
+g_return_val_if_fail(route, FALSE);
+
+if (route->head==route->tail) {
+       MACRO_BANNER_SHOW_INFO(_window, _("No route exist."));
        return FALSE;
 }
 
-g_assert(track);
-if (abs((gint)gps->unitx-track->tail->unitx) > sensitivity || abs((gint)gps->unity-track->tail->unity) > sensitivity) {
-
-       /* If gps is available, update the nearest-waypoint data. */
-       /* XXX: MOVE THIS */
-       if (gps && _route->head != _route->tail && (gps->newly_fixed ? (route_find_nearest_point(_route), TRUE) : route_update_nears(_route, TRUE))) {
-               /* Nearest waypoint has changed - re-render paths. */
-               map_render_paths();
-               MACRO_QUEUE_DRAW_AREA();
+if (file_save(&_route_dir_uri, &_route_dir_uri, &handle)) {
+       if (path_gpx_write(route, handle)) {
+               MACRO_BANNER_SHOW_INFO(_window, _("Route Saved"));
+       } else {
+               popup_error(_window, _("Error writing GPX file."));
        }
+       gnome_vfs_close(handle);
+       return TRUE;
+}
+return FALSE;
+}
 
-       if (_show_tracks & TRACKS_MASK) {
-               gint tx1, ty1, tx2, ty2;
-
-               /* Instead of calling map_render_paths(), we'll draw the new line
-                * ourselves and call gtk_widget_queue_draw_area(). */
-               map_render_segment(_gc[COLORABLE_TRACK], _gc[COLORABLE_TRACK_BREAK], 
-                       track->tail->unitx, track->tail->unity, gps->unitx, gps->unity);
-
-               if (track->tail->unity && track->tail->unitx) {
-                       tx1 = unit2x(track->tail->unitx);
-                       ty1 = unit2y(track->tail->unity);
-                       tx2 = unit2x(gps->unitx);
-                       ty2 = unit2y(gps->unity);
-
-                       /* XXX: This should not be here... */
-                       gtk_widget_queue_draw_area(_map_widget,
-                                          MIN(tx1, tx2) - _draw_width, 
-                                          MIN(ty1, ty2) - _draw_width,
-                                          abs(tx1 - tx2) + (2 * _draw_width),
-                                          abs(ty1 - ty2) + (2 * _draw_width));
+/**
+ *
+ */
+static gboolean 
+route_origin_type_selected_cb(GtkWidget *toggle, OriginToggleInfo *oti)
+{
+if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) {
+       if (toggle == oti->rad_use_gps) {
+               gchar buffer[80];
+               gchar strlat[32];
+               gchar strlon[32];
+               g_ascii_formatd(strlat, 32, "%.06f", _gps->data.lat);
+               g_ascii_formatd(strlon, 32, "%.06f", _gps->data.lon);
+               g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
+               gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
+       } else if (toggle == oti->rad_use_route) {
+               gchar buffer[80];
+               gchar strlat[32];
+               gchar strlon[32];
+               gdouble lat, lon;
+               Point *p;
+
+               p=path_find_last_point(oti->path);
+               if (p) {
+                       unit2latlon(p->unitx, p->unity, &lat, &lon);
+                       g_ascii_formatd(strlat, 32, "%.06f", lat);
+                       g_ascii_formatd(strlon, 32, "%.06f", lon);
+                       g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
+                       gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
                }
        }
+       gtk_widget_set_sensitive(oti->txt_from, toggle == oti->rad_use_text);
+       gtk_widget_set_sensitive(oti->chk_auto, toggle == oti->rad_use_gps);
+}
+return TRUE;
+}
 
-       if (track->tail->unity && track->tail->unitx) {
-               gdouble lat, lon;
+/**
+ * Cancel the current auto-route.
+ */
+void 
+route_cancel_autoroute(Path *route, gboolean temporary)
+{
+if (_autoroute_data.enabled) {
+       if (!temporary) {
+               _autoroute_data.enabled = FALSE;
+
+               g_free(_autoroute_data.dest);
+               _autoroute_data.dest = NULL;
 
-               unit2latlon(track->tail->unitx, track->tail->unity, lat, lon);
-               track->length += calculate_distance(lat, lon, gps->lat, gps->lon);
-               track->tspeed+=gps->speed;
-               if (track->points>0)
-                       track->avgspeed=track->tspeed/track->points;
-               else
-                       track->avgspeed=0.0;
-               g_debug("TRACK: %f %f (%d)", track->length, track->avgspeed, track->points);
+               g_free(_autoroute_data.src_str);
+               _autoroute_data.src_str = NULL;
        }
 
-       MACRO_PATH_INCREMENT_TAIL(*track);
-       track->tail->unitx=gps->unitx;
-       track->tail->unity=gps->unity;
-       track->tail->time=gps->time;
-       track->tail->altitude=gps->altitude;
-       track->maxspeed=gps->maxspeed;
-       track->points++;
+       if (_autoroute_data.curl_easy) {
+               if (_curl_multi)
+                       curl_multi_remove_handle(_curl_multi, _autoroute_data.curl_easy);
+               curl_easy_cleanup(_autoroute_data.curl_easy);
+               _autoroute_data.curl_easy = NULL;
+       }
+
+       g_free(_autoroute_data.rdl_data.bytes);
+       _autoroute_data.rdl_data.bytes = NULL;
+       _autoroute_data.rdl_data.bytes_read = 0;
+
+       _autoroute_data.in_progress = FALSE;
+}
+}
+
+/**
+ * Read the data provided by the given handle as GPX data, updating the
+ * auto-route with that data.
+ */
+size_t
+route_dl_cb_read(void *ptr, size_t size, size_t nmemb, RouteDownloadData * rdl_data)
+{
+size_t old_size = rdl_data->bytes_read;
+
+rdl_data->bytes_read += size * nmemb;
+rdl_data->bytes = g_renew(gchar, rdl_data->bytes, rdl_data->bytes_read);
+g_memmove(rdl_data->bytes + old_size, ptr, size * nmemb);
+
+return (size * nmemb);
 }
 
+gboolean
+route_auto_route_dl_idle_cb()
+{
+gchar latstr[32], lonstr[32], *latlonstr;
+
+g_ascii_dtostr(latstr, 32, _gps->data.lat);
+g_ascii_dtostr(lonstr, 32, _gps->data.lon);
+latlonstr = g_strdup_printf("%s,%s", latstr, lonstr);
+_autoroute_data.src_str = g_strdup_printf(_route_dl_url, latlonstr, _autoroute_data.dest);
+g_free(latlonstr);
+
+MACRO_CURL_EASY_INIT(_autoroute_data.curl_easy);
+curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_URL, _autoroute_data.src_str);
+curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEFUNCTION, route_dl_cb_read);
+curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEDATA, &_autoroute_data.rdl_data);
+curl_multi_add_handle(_curl_multi, _autoroute_data.curl_easy);
+
+if (iap_is_connected() && !_curl_sid)
+       _curl_sid = g_timeout_add(100, (GSourceFunc)map_download_timeout, NULL);
+
+_autoroute_data.in_progress = TRUE;
+
+return FALSE;
+}
+
+/**
+ * Display a dialog box to the user asking them to download a route.  The
+ * "From" and "To" textfields may be initialized using the first two
+ * parameters.  The third parameter, if set to TRUE, will cause the "Use GPS
+ * Location" checkbox to be enabled, which automatically sets the "From" to the
+ * current GPS position (this overrides any value that may have been passed as
+ * the "To" initializer).
+ * None of the passed strings are freed - that is left to the caller, and it is
+ * safe to free either string as soon as this function returns.
+ */
+gboolean 
+route_download(Path *route, gchar *to)
+{
+GtkWidget *dialog;
+GtkWidget *table;
+GtkWidget *label;
+GtkWidget *txt_source_url;
+GtkWidget *hbox;
+OriginToggleInfo oti;
+GtkEntryCompletion *from_comp;
+GtkEntryCompletion *to_comp;
+gboolean r=FALSE;
+
+oti.path=route;
+
+dialog = gtk_dialog_new_with_buttons(_("Download Route"),
+                            GTK_WINDOW(_window),
+                            GTK_DIALOG_MODAL, GTK_STOCK_OK,
+                            GTK_RESPONSE_ACCEPT,
+                            GTK_STOCK_CANCEL,
+                            GTK_RESPONSE_REJECT, NULL);
+
+help_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_DOWNROUTE);
+gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 5, FALSE), TRUE, TRUE, 0);
+
+from_comp = gtk_entry_completion_new();
+gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model));
+gtk_entry_completion_set_text_column(from_comp, 0);
+to_comp = gtk_entry_completion_new();
+gtk_entry_completion_set_model(to_comp, GTK_TREE_MODEL(_loc_model));
+gtk_entry_completion_set_text_column(to_comp, 0);
+
+/* Source URL. */
+gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Source URL")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+gtk_table_attach(GTK_TABLE(table), txt_source_url = gtk_entry_new(), 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+gtk_entry_set_width_chars(GTK_ENTRY(txt_source_url), 25);
+
+/* Auto. */
+gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 1, 2, GTK_FILL, 0, 2, 4);
+gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_gps = gtk_radio_button_new_with_label(NULL, _("Use GPS Location")), TRUE, TRUE, 0);
+gtk_box_pack_start(GTK_BOX(hbox), oti.chk_auto = gtk_check_button_new_with_label(_("Auto-Update")), TRUE, TRUE, 0);
+gtk_widget_set_sensitive(oti.chk_auto, FALSE);
+
+/* Use End of Route. */
+gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 2, 3, GTK_FILL, 0, 2, 4);
+gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_route = gtk_radio_button_new_with_label_from_widget
+                  (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Use End of Route")), TRUE, TRUE, 0);
+gtk_widget_set_sensitive(oti.rad_use_route, route->head != route->tail);
+
+/* Origin. */
+gtk_table_attach(GTK_TABLE(table), oti.rad_use_text = gtk_radio_button_new_with_label_from_widget
+                (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Origin")), 0, 1, 3, 4, GTK_FILL, 0, 2, 4);
+gtk_table_attach(GTK_TABLE(table), oti.txt_from = gtk_entry_new(), 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+gtk_entry_set_completion(GTK_ENTRY(oti.txt_from), from_comp);
+gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_from), 25);
+
+/* Destination. */
+gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Destination")), 0, 1, 4, 5, GTK_FILL, 0, 2, 4);
+gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+gtk_table_attach(GTK_TABLE(table), oti.txt_to = gtk_entry_new(), 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+gtk_entry_set_completion(GTK_ENTRY(oti.txt_to), to_comp);
+gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_to), 25);
+
+g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti);
+g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti);
+g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti);
+
+#if defined (WITH_HILDON) && defined (HILDON_AUTOCAP)
+g_object_set(G_OBJECT(oti.txt_from), HILDON_AUTOCAP, FALSE, NULL);
+g_object_set(G_OBJECT(oti.txt_to), HILDON_AUTOCAP, FALSE, NULL);
+#endif
+
+/* Initialize fields. */
+gtk_entry_set_text(GTK_ENTRY(txt_source_url), _route_dl_url);
+gtk_entry_set_text(GTK_ENTRY(oti.txt_to), (to ? to : ""));
+
+gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE);
+
+if (route->head != route->tail) {
+       /* Use "End of Route" by default if they have a route. */
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_route), TRUE);
+       gtk_widget_grab_focus(oti.rad_use_route);
+} else if (_enable_gps) {
+       /* Else use "GPS Location" if they have GPS enabled. */
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps), TRUE);
+       gtk_widget_grab_focus(oti.rad_use_gps);
+} else {
+       /* Else use text. */
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE);
+       gtk_widget_grab_focus(oti.txt_from);
+}
+
+gtk_widget_show_all(dialog);
+
+while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
+       CURL *curl_easy;
+       RouteDownloadData rdl_data = { 0, 0 };
+       gchar buffer[BUFFER_SIZE];
+       const gchar *source_url, *from, *to;
+       gchar *from_escaped, *to_escaped;
+
+       source_url = gtk_entry_get_text(GTK_ENTRY(txt_source_url));
+       if (!strlen(source_url)) {
+               popup_error(dialog, _("Please specify a source URL."));
+               continue;
+       } else {
+               g_free(_route_dl_url);
+               _route_dl_url = g_strdup(source_url);
+       }
+
+       from = gtk_entry_get_text(GTK_ENTRY(oti.txt_from));
+       if (!strlen(from)) {
+               popup_error(dialog, _("Please specify a start location."));
+               continue;
+       }
+
+       to = gtk_entry_get_text(GTK_ENTRY(oti.txt_to));
+       if (!strlen(to)) {
+               popup_error(dialog, _("Please specify an end location."));
+               continue;
+       }
+
+       from_escaped = gnome_vfs_escape_string(from);
+       to_escaped = gnome_vfs_escape_string(to);
+       g_snprintf(buffer, sizeof(buffer), source_url, from_escaped, to_escaped);
+       g_free(from_escaped);
+       g_free(to_escaped);
+
+       iap_connect();
+
+       /* Attempt to download the route from the server. */
+       MACRO_CURL_EASY_INIT(curl_easy);
+       curl_easy_setopt(curl_easy, CURLOPT_URL, buffer);
+       curl_easy_setopt(curl_easy, CURLOPT_WRITEFUNCTION, route_dl_cb_read);
+       curl_easy_setopt(curl_easy, CURLOPT_WRITEDATA, &rdl_data);
+       if (CURLE_OK != curl_easy_perform(curl_easy)) {
+               popup_error(dialog, _("Failed to connect to GPX Directions server"));
+               curl_easy_cleanup(curl_easy);
+               g_free(rdl_data.bytes);
+               /* Let them try again */
+               continue;
+       }
+       curl_easy_cleanup(curl_easy);
+
+       if (strncmp(rdl_data.bytes, "<?xml", strlen("<?xml"))) {
+               /* Not an XML document - must be bad locations. */
+               popup_error(dialog, _("Could not generate directions. Make sure your source and destination are valid."));
+               g_free(rdl_data.bytes);
+               /* Let them try again. */
+       }
+       /* Else, if GPS is enabled, replace the route, otherwise append it. */
+       else if (gpx_parse(route, rdl_data.bytes, rdl_data.bytes_read,
+                       (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps)) ? GPX_PATH_NEW : GPX_PATH_APPEND))) {
+               GtkTreeIter iter;
+
+               /* Find the nearest route point, if we're connected. */
+               path_find_nearest_point(route);
+
+               /* Cancel any autoroute that might be occurring. */
+               route_cancel_autoroute(route, FALSE);
+
+               if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.chk_auto))) {
+                       /* Kick off a timeout to start the first update. */
+                       _autoroute_data.dest = gnome_vfs_escape_string(to);
+                       _autoroute_data.enabled = TRUE;
+               }
+
+               /* Save Origin in Route Locations list if not from GPS. */
+               if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps)) && !g_slist_find_custom(_loc_list, from, (GCompareFunc) strcmp)) {
+                       _loc_list = g_slist_prepend(_loc_list, g_strdup(from));
+                       gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, from, -1);
+               }
+
+               /* Save Destination in Route Locations list. */
+               if (!g_slist_find_custom(_loc_list, to, (GCompareFunc) strcmp)) {
+                       _loc_list = g_slist_prepend(_loc_list, g_strdup(to));
+                       gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, to, -1);
+               }
+
+               MACRO_BANNER_SHOW_INFO(_window, _("Route Downloaded"));
+               g_free(rdl_data.bytes);
+               route_set_destination_from_last(route, &_dest);
+
+               /* Success! Get out of the while loop. */
+               r=TRUE;
+               break;
+       } else {
+               popup_error(dialog, _("Error parsing route GPX data."));
+               g_free(rdl_data.bytes);
+               /* Let them try again. */
+       }
+}
+
+gtk_widget_hide(dialog);       /* Destroying causes a crash (!?!?!??!) */
+
+return r;
+}
+
+/**
+ * Show the distance from the current GPS location to the given point,
+ * following the route. If point is NULL, then the distance is shown to the
+ * next waypoint.
+ */
+gboolean 
+route_show_distance_to(Path *route, Point *point)
+{
+gchar buffer[80];
+gdouble lat, lon;
+gdouble sum;
+
+g_return_val_if_fail(route, FALSE);
+g_return_val_if_fail(point, FALSE);
+
+unit2latlon(point->unitx, point->unity, &lat, &lon);
+sum=path_get_distance_to(route, point, lat, lon);
+g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
+MACRO_BANNER_SHOW_INFO(_window, buffer);
+
 return TRUE;
 }
 
+void 
+route_show_distance_to_next_waypoint(Path *route)
+{
+g_return_if_fail(route);
+
+if (!route_show_distance_to(route, NULL))
+       MACRO_BANNER_SHOW_INFO(_window, _("There is no next waypoint."));
+}
+
+void 
+route_show_distance_to_last(Path *route)
+{
+g_return_if_fail(route);
+
+if (route->head != route->tail) {
+       route_show_distance_to(route, path_find_last_point(route));
+} else {
+       MACRO_BANNER_SHOW_INFO(_window, _("The current route is empty."));
+}
+}
+
 gboolean
 track_open(Path *track)
 {
@@ -172,8 +529,7 @@ gint size;
 gboolean r = FALSE;
 
 if (file_open_get_contents(&_track_file_uri, &buffer, &size)) {
-       if (gpx_parse(track, buffer, size, GPX_PATH_NEW)) {
-               map_force_redraw();
+       if (path_gpx_parse(track, buffer, size, GPX_PATH_NEW)) {
                MACRO_BANNER_SHOW_INFO(_window, _("Track Opened"));
                r = TRUE;
        } else {
@@ -191,10 +547,10 @@ GnomeVFSHandle *handle;
 gboolean r = FALSE;
 
 if (file_save(&_track_file_uri, &_track_file_uri, &handle)) {
-       if (gpx_write(track, handle)) {
+       if (path_gpx_write(track, handle)) {
                MACRO_BANNER_SHOW_INFO(_window, _("Track Saved"));
                r = TRUE;
-               track_clear(track);
+               path_clear_ask(track);
        } else {
                popup_error(_window, _("Error writing GPX file."));
        }
@@ -227,10 +583,10 @@ dialog = gtk_dialog_new_with_buttons(_("Insert Mark"),
 
 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0);
 
-gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Near Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
 
-unit2latlon(_gps->data.unitx, _gps->data.unity, lat, lon);
+unit2latlon(_gps->data.unitx, _gps->data.unity, &lat, &lon);
 lat_format(_degformat, lat, tmp1);
 lon_format(_degformat, lon, tmp2);
 p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2);
index 352504a6fae51d4ab7d49fde0be77849dcf06b00..a19760b97b8a97db100713b745a5da0a900d1ab7 100644 (file)
@@ -8,16 +8,21 @@
 
 Path *_track;
 
-#define TRACK_SQL_SELECT_TRACKS "select id,name,slat,slon,elat,elon,len,sdate,edate from tracks order by sdate"
-#define TRACK_SQL_INSERT_TRACK "insert into tracks (id,name,sloc,sdate) values (?,?,?,?);
-#define TRACK_SQL_INSERT_TRACK_POINT "insert into trackpoints (tid,dt,lat,lon,alt,hdop,vdop,pdop,sat,fix) values (?,?,?,?,?,?,?,?,?,?)"
-#define TRACK_SQL_SELECT_TRACK_POINTS "select tid,dt,lat,lon,alt,hdop,vdop,pdop,sat,fix from trackpoints where tid=? order by dt"
 
-void track_init(void);
-void track_deinit(void);
+/** The singleton auto-route-download data. */
+AutoRouteDownloadData _autoroute_data;
+
+gboolean route_open_file(Path *route);
+gboolean route_save(Path *route);
+gboolean route_download(Path *route, gchar *to);
+gboolean route_clear(Path *route);
+
+void route_autoroute_check(Path *route);
+gboolean route_show_distance_to(Path *route, Point *point);
+void route_show_distance_to_last(Path *route);
+void route_show_distance_to_next(Path *route);
+
 
-gboolean track_add(Path *track, GpsData *gps);
-gboolean track_insert_mark(Path *track);
 gboolean track_save(Path *track);
 gboolean track_open(Path *track);
 void track_clear(Path *track);