]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Merge branch 'i18n-launchpad'
[andy/viking.git] / src / viktrwlayer.c
index 9fb218ed5059e281175b995af8529c5020c84358..05dc83fec6ff2fa257840befec1c782712a65586 100644 (file)
@@ -39,7 +39,7 @@
 #include "babel.h"
 #include "dem.h"
 #include "dems.h"
-#include "googlesearch.h"
+#include "geonamessearch.h"
 #ifdef VIK_CONFIG_OPENSTREETMAP
 #include "osm-traces.h"
 #endif
 
 #include "icons/icons.h"
 
+#ifdef HAVE_MATH_H
 #include <math.h>
+#endif
+#ifdef HAVE_STRING_H
 #include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
+#endif
 #include <stdio.h>
 #include <ctype.h>
 
@@ -65,7 +71,7 @@ static gboolean return_true (gpointer a, gpointer b, gpointer c) { return TRUE;
 static g_hash_table_remove_all (GHashTable *ght) { g_hash_table_foreach_remove ( ght, (GHRFunc) return_true, FALSE ); }
 #endif
 
-#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=js"
+#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=kml"
 #define VIK_TRW_LAYER_TRACK_GC 13
 #define VIK_TRW_LAYER_TRACK_GC_RATES 10
 #define VIK_TRW_LAYER_TRACK_GC_MIN 0
@@ -206,6 +212,7 @@ static void trw_layer_cut_item_cb( gpointer *pass_along);
 
 static void trw_layer_find_maxmin_waypoints ( const gchar *name, const VikWaypoint *w, struct LatLon maxmin[2] );
 static void trw_layer_find_maxmin_tracks ( const gchar *name, GList **t, struct LatLon maxmin[2] );    
+static void trw_layer_find_maxmin (VikTrwLayer *vtl, struct LatLon maxmin[2]);
 
 static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp );
 static void trw_layer_free_track_gcs ( VikTrwLayer *vtl );
@@ -224,6 +231,9 @@ static void trw_layer_centerize ( gpointer layer_and_vlp[2] );
 static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type );
 static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] );
 static void trw_layer_new_wp ( gpointer lav[2] );
+static void trw_layer_new_wikipedia_wp_viewport ( gpointer lav[2] );
+static void trw_layer_new_wikipedia_wp_layer ( gpointer lav[2] );
+static void trw_layer_merge_with_other ( gpointer pass_along[6] );
 
 /* pop-up items */
 static void trw_layer_properties_item ( gpointer pass_along[5] );
@@ -236,7 +246,7 @@ static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp );
 
 
 static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len );
-static VikTrwLayer *trw_layer_unmarshall( gpointer data, gint len, VikViewport *vvp );
+static VikTrwLayer *trw_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
 
 static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp );
 static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id );
@@ -593,7 +603,7 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara
                      trw_layer_new_track_gcs ( vtl, vp );
                    }
                    break;
-    case PARAM_BLT: if ( data.u > 0 && data.u <= 8 && data.u != vtl->bg_line_thickness )
+    case PARAM_BLT: if ( data.u >= 0 && data.u <= 8 && data.u != vtl->bg_line_thickness )
                    {
                      vtl->bg_line_thickness = data.u;
                      trw_layer_new_track_gcs ( vtl, vp );
@@ -665,8 +675,10 @@ static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id )
 
 static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len )
 {
-  guint8 *pd, *dd;
-  gint pl, dl;
+  guint8 *pd;
+  gchar *dd;
+  gsize dl;
+  gint pl;
   gchar *tmpname;
   FILE *f;
 
@@ -677,7 +689,7 @@ static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len )
     vik_layer_marshall_params(VIK_LAYER(vtl), &pd, &pl);
     fclose(f);
     f = NULL;
-    g_file_get_contents(tmpname, (void *)&dd, (void *)&dl, NULL);
+    g_file_get_contents(tmpname, &dd, &dl, NULL);
     *len = sizeof(pl) + pl + dl;
     *data = g_malloc(*len);
     memcpy(*data, &pl, sizeof(pl));
@@ -691,10 +703,10 @@ static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len )
   }
 }
 
-static VikTrwLayer *trw_layer_unmarshall( gpointer data, gint len, VikViewport *vvp )
+static VikTrwLayer *trw_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
 {
   VikTrwLayer *rv = VIK_TRW_LAYER(vik_layer_create ( VIK_LAYER_TRW, vvp, NULL, FALSE ));
-  guint pl;
+  gint pl;
   gchar *tmpname;
   FILE *f;
 
@@ -956,6 +968,9 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
     drawstops = dp->vtl->drawstops;
   }
 
+  if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
+    dp->track_gc_iter = VIK_TRW_LAYER_TRACK_GC_BLACK;
+
   if ( track == dp->vtl->current_track )
     main_gc = dp->vtl->current_track_gc;
   else
@@ -978,9 +993,6 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
     oldx = x;
     oldy = y;
 
-    if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
-      dp->track_gc_iter = VIK_TRW_LAYER_TRACK_GC_MAX + 1;
-
     while ((list = g_list_next(list)))
     {
       tp = VIK_TRACKPOINT(list->data);
@@ -1113,7 +1125,7 @@ static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct
              wp->coord.north_south > dp->cn1 && wp->coord.north_south < dp->cn2 ) )
   {
     gint x, y;
-    GdkPixbuf *sym;
+    GdkPixbuf *sym = NULL;
     vik_viewport_coord_to_screen ( dp->vp, &(wp->coord), &x, &y );
 
     /* if in shrunken_cache, get that. If not, get and add to shrunken_cache */
@@ -1211,11 +1223,18 @@ static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct
     if ( dp->vtl->drawlabels )
     {
       /* thanks to the GPSDrive people (Fritz Ganter et al.) for hints on this part ... yah, I'm too lazy to study documentation */
+      gint label_x, label_y;
       gint width, height;
       pango_layout_set_text ( dp->vtl->wplabellayout, name, -1 );
       pango_layout_get_pixel_size ( dp->vtl->wplabellayout, &width, &height );
-      vik_viewport_draw_rectangle ( dp->vp, dp->vtl->waypoint_bg_gc, TRUE, x + dp->vtl->wp_size - 1, y-1,width+1,height-1);
-      vik_viewport_draw_layout ( dp->vp, dp->vtl->waypoint_text_gc, x + dp->vtl->wp_size, y, dp->vtl->wplabellayout );
+      label_x = x - width/2;
+      if (sym)
+        label_y = y - height - 2 - gdk_pixbuf_get_height(sym)/2;
+      else
+        label_y = y - dp->vtl->wp_size - height - 2;
+
+      vik_viewport_draw_rectangle ( dp->vp, dp->vtl->waypoint_bg_gc, TRUE, label_x - 1, label_y-1,width+2,height+2);
+      vik_viewport_draw_layout ( dp->vp, dp->vtl->waypoint_text_gc, label_x, label_y, dp->vtl->wplabellayout );
     }
   }
 }
@@ -1464,13 +1483,44 @@ static void trw_layer_find_maxmin_tracks ( const gchar *name, GList **t, struct
   }
 }
 
+static void trw_layer_find_maxmin (VikTrwLayer *vtl, struct LatLon maxmin[2])
+{
+  struct LatLon wpt_maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
+  struct LatLon trk_maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
+  
+  g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_find_maxmin_waypoints, wpt_maxmin );
+  g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_find_maxmin_tracks, trk_maxmin );
+  if ((wpt_maxmin[0].lat != 0.0 && wpt_maxmin[0].lat > trk_maxmin[0].lat) || trk_maxmin[0].lat == 0.0) {
+    maxmin[0].lat = wpt_maxmin[0].lat;
+  }
+  else {
+    maxmin[0].lat = trk_maxmin[0].lat;
+  }
+  if ((wpt_maxmin[0].lon != 0.0 && wpt_maxmin[0].lon > trk_maxmin[0].lon) || trk_maxmin[0].lon == 0.0) {
+    maxmin[0].lon = wpt_maxmin[0].lon;
+  }
+  else {
+    maxmin[0].lon = trk_maxmin[0].lon;
+  }
+  if ((wpt_maxmin[1].lat != 0.0 && wpt_maxmin[1].lat < trk_maxmin[1].lat) || trk_maxmin[1].lat == 0.0) {
+    maxmin[1].lat = wpt_maxmin[1].lat;
+  }
+  else {
+    maxmin[1].lat = trk_maxmin[1].lat;
+  }
+  if ((wpt_maxmin[1].lon != 0.0 && wpt_maxmin[1].lon < trk_maxmin[1].lon) || trk_maxmin[1].lon == 0.0) {
+    maxmin[1].lon = wpt_maxmin[1].lon;
+  }
+  else {
+    maxmin[1].lon = trk_maxmin[1].lon;
+  }
+}
 
 gboolean vik_trw_layer_find_center ( VikTrwLayer *vtl, VikCoord *dest )
 {
   /* TODO: what if there's only one waypoint @ 0,0, it will think nothing found. like I don't have more important things to worry about... */
   struct LatLon maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
-  g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_find_maxmin_waypoints, maxmin );
-  g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_find_maxmin_tracks, maxmin );
+  trw_layer_find_maxmin (vtl, maxmin);
   if (maxmin[0].lat == 0.0 && maxmin[0].lon == 0.0 && maxmin[1].lat == 0.0 && maxmin[1].lon == 0.0)
     return FALSE;
   else
@@ -1501,7 +1551,7 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type )
                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                      NULL);
-  gtk_file_chooser_set_filename (GTK_FILE_CHOOSER(file_selector), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])));
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(file_selector), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])));
 
   while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
   {
@@ -1545,7 +1595,7 @@ static void trw_layer_export_gpx ( gpointer layer_and_vlp[2] )
 static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
 {
   GHashTable *wps = vik_trw_layer_get_waypoints ( VIK_TRW_LAYER(layer_and_vlp[0]) );
-  GtkWidget *dia = gtk_dialog_new_with_buttons (_("Create"),
+  GtkWidget *dia = gtk_dialog_new_with_buttons (_("Find"),
                                                  VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]),
                                                  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                                  GTK_STOCK_CANCEL,
@@ -1595,7 +1645,6 @@ gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikC
   gchar *name = highest_wp_number_get(vtl);
   VikWaypoint *wp = vik_waypoint_new();
   wp->coord = *def_coord;
-  wp->altitude = VIK_DEFAULT_ALTITUDE;
 
   if ( a_dialog_new_waypoint ( w, &name, wp, vik_trw_layer_get_waypoints ( vtl ), vtl->coord_mode ) )
   {
@@ -1607,6 +1656,49 @@ gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikC
   return FALSE;
 }
 
+static void trw_layer_new_wikipedia_wp_viewport ( gpointer lav[2] )
+{
+  VikCoord one, two;
+  struct LatLon one_ll, two_ll;
+  struct LatLon maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
+
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
+  VikViewport *vvp =  vik_window_viewport(vw);
+  vik_viewport_screen_to_coord ( vvp, 0, 0, &one);
+  vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &two);
+  vik_coord_to_latlon(&one, &one_ll);
+  vik_coord_to_latlon(&two, &two_ll);
+  if (one_ll.lat > two_ll.lat) {
+    maxmin[0].lat = one_ll.lat;
+    maxmin[1].lat = two_ll.lat;
+  }
+  else {
+    maxmin[0].lat = two_ll.lat;
+    maxmin[1].lat = one_ll.lat;
+  }
+  if (one_ll.lon > two_ll.lon) {
+    maxmin[0].lon = one_ll.lon;
+    maxmin[1].lon = two_ll.lon;
+  }
+  else {
+    maxmin[0].lon = two_ll.lon;
+    maxmin[1].lon = one_ll.lon;
+  }
+  a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, vlp, maxmin);
+}
+
+static void trw_layer_new_wikipedia_wp_layer ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  struct LatLon maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
+  
+  trw_layer_find_maxmin (vtl, maxmin);
+  a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, vlp, maxmin);
+}
+
 static void trw_layer_new_wp ( gpointer lav[2] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
@@ -1622,6 +1714,7 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl
   static gpointer pass_along[2];
   GtkWidget *item;
   GtkWidget *export_submenu;
+  GtkWidget *wikipedia_submenu;
   pass_along[0] = vtl;
   pass_along[1] = vlp;
 
@@ -1665,6 +1758,24 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
 
+#ifdef VIK_CONFIG_GEONAMES
+  wikipedia_submenu = gtk_menu_new();
+  item = gtk_menu_item_new_with_label ( _("Add Wikipedia Waypoints") );
+  gtk_menu_shell_append(GTK_MENU_SHELL (menu), item);
+  gtk_widget_show(item);
+  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), wikipedia_submenu);
+
+  item = gtk_menu_item_new_with_label ( _("Within layer bounds") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_layer), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
+  gtk_widget_show ( item );
+
+  item = gtk_menu_item_new_with_label ( _("Within current view") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_viewport), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
+  gtk_widget_show ( item );
+#endif
+
 #ifdef VIK_CONFIG_OPENSTREETMAP 
   item = gtk_menu_item_new_with_label ( _("Upload to OSM") );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_cb), pass_along );
@@ -1726,9 +1837,9 @@ void vik_trw_layer_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
     {
       GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
-      vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE );
+      vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, t->visible, TRUE );
 #else
-      vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE );
+      vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, t->visible, TRUE );
 #endif
       vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, iter );
       g_hash_table_insert ( vtl->tracks_iters, name, iter );
@@ -2065,6 +2176,39 @@ static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] )
  * merge/split by time routines 
  *************************************/
 
+/* called for each key in track hash table.
+ * If the current track has time stamp, add it to the result,
+ * except the one pointed by "exclude".
+ * set exclude to NULL if there is no exclude to check.
+ * Not that result is in reverse (for performance reason).
+ */
+typedef struct {
+  GList **result;
+  GList  *exclude;
+} twt_udata;
+static void find_tracks_with_timestamp(gpointer key, gpointer value, gpointer udata)
+{
+  twt_udata *user_data = udata;
+  VikTrackpoint *p1, *p2;
+
+  if (VIK_TRACK(value)->trackpoints == user_data->exclude) {
+    return;
+  }
+
+  if (VIK_TRACK(value)->trackpoints) {
+    p1 = VIK_TRACKPOINT(VIK_TRACK(value)->trackpoints->data);
+    p2 = VIK_TRACKPOINT(g_list_last(VIK_TRACK(value)->trackpoints)->data);
+
+    if (!p1->has_timestamp || !p2->has_timestamp) {
+      g_print("no timestamp\n");
+      return;
+    }
+
+  }
+
+  *(user_data->result) = g_list_prepend(*(user_data->result), key);
+}
+
 /* called for each key in track hash table. if original track user_data[1] is close enough
  * to the passed one, add it to list in user_data[0] 
  */
@@ -2135,6 +2279,58 @@ static gint trackpoint_compare(gconstpointer a, gconstpointer b)
   return 0;
 }
 
+static void trw_layer_merge_with_other ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  gchar *orig_track_name = pass_along[3];
+  GList *tracks_with_timestamp = NULL;
+  VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name );
+
+  if (track->trackpoints &&
+      !VIK_TRACKPOINT(track->trackpoints->data)->has_timestamp) {
+    a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. This track does not have timestamp"));
+    return;
+  }
+
+  if (1) {
+
+    twt_udata udata;
+    udata.result = &tracks_with_timestamp;
+    udata.exclude = track->trackpoints;
+    g_hash_table_foreach(vtl->tracks, find_tracks_with_timestamp, (gpointer)&udata);
+    tracks_with_timestamp = g_list_reverse(tracks_with_timestamp);
+  }
+
+  if (!tracks_with_timestamp) {
+    a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. No other track in this layer has timestamp"));
+    return;
+  }
+
+  GList *merge_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+      vtl->tracks, tracks_with_timestamp, TRUE,
+      _("Merge with..."), _("Select track to merge with"));
+  g_list_free(tracks_with_timestamp);
+
+  if (merge_list)
+  {
+    GList *l;
+    for (l = merge_list; l != NULL; l = g_list_next(l)) {
+      VikTrack *merge_track = (VikTrack *) g_hash_table_lookup (vtl->tracks, l->data );
+      if (merge_track) {
+        track->trackpoints = g_list_concat(track->trackpoints, merge_track->trackpoints);
+        merge_track->trackpoints = NULL;
+        vik_trw_layer_delete_track(vtl, l->data);
+        track->trackpoints = g_list_sort(track->trackpoints, trackpoint_compare);
+      }
+    }
+    /* TODO: free data before free merge_list */
+    for (l = merge_list; l != NULL; l = g_list_next(l))
+      g_free(l->data);
+    g_list_free(merge_list);
+    vik_layer_emit_update( VIK_LAYER(vtl) );
+  }
+}
+
 /* merge by time routine */
 static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
 {
@@ -2152,6 +2348,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
                               _("Merge Threshold..."), 
                               _("Merge when time between tracks less than:"), 
                               &thr)) {
+    free(orig_track_name);
     return;
   }
 
@@ -2364,7 +2561,7 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar
       return NULL;
 
     if (strcasecmp(newname, sublayer)) { /* Not just changing case */
-      if (g_hash_table_lookup( l->waypoints, newname))
+      if (g_hash_table_lookup( l->tracks, newname))
       {
         a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Track Already Exists") );
         return NULL;
@@ -2531,6 +2728,11 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
+    item = gtk_menu_item_new_with_label ( _("Merge With Other Tracks...") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_with_other), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_widget_show ( item );
+
     item = gtk_menu_item_new_with_label ( _("Split By Time") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_timestamp), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
@@ -2638,7 +2840,7 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
   else if ( response == VIK_TRW_LAYER_TPWIN_SPLIT && vtl->current_tpl->next && vtl->current_tpl->prev )
   {
     gchar *name;
-    if ( ( name = a_dialog_new_track ( GTK_WINDOW(vtl->tpwin), vtl->tracks ) ) )
+    if ( ( name = a_dialog_new_track ( GTK_WINDOW(vtl->tpwin), vtl->tracks, NULL ) ) )
     {
       VikTrack *tr = vik_track_new ();
       GList *newglist = g_list_alloc ();
@@ -2655,6 +2857,8 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
 
       vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track_name );
 
+      tr->visible = TRUE;
+
       vik_trw_layer_add_track ( vtl, name, tr );
       vik_layer_emit_update(VIK_LAYER(vtl));
     }
@@ -3202,8 +3406,8 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event,
 
   if ( ! vtl->current_track )
   {
-    gchar *name;
-    if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks ) ) )
+    gchar *name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, _("Track"));
+    if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks, name ) ) )
     {
       vtl->current_track = vik_track_new();
       vtl->current_track->visible = TRUE;
@@ -3229,7 +3433,6 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event,
   tp->newsegment = FALSE;
   tp->has_timestamp = FALSE;
   tp->timestamp = 0;
-  tp->altitude = VIK_DEFAULT_ALTITUDE;
   vtl->current_track->trackpoints = g_list_append ( vtl->current_track->trackpoints, tp );
 
   vtl->ct_x1 = vtl->ct_x2;
@@ -3454,7 +3657,7 @@ static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *ev
                           g_ascii_dtostr (startlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lon),
                           g_ascii_dtostr (endlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lat),
                           g_ascii_dtostr (endlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lon));
-    a_babel_convert_from_url ( vtl, url, "google", NULL, NULL );
+    a_babel_convert_from_url ( vtl, url, "kml", NULL, NULL );
     g_free ( url );
 
     /* see if anything was done -- a track was added or appended to */
@@ -3464,7 +3667,7 @@ static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *ev
       tr = g_hash_table_lookup ( vtl->tracks, vtl->magic_scissors_added_track_name );
 
       if ( tr )
-        vik_track_set_comment_no_copy ( tr, g_strdup_printf("from: %f,%f to: %f%f", start.lat, start.lon, end.lat, end.lon ) ); 
+        vik_track_set_comment_no_copy ( tr, g_strdup_printf("from: %f,%f to: %f,%f", start.lat, start.lon, end.lat, end.lon ) );
  
       vtl->magic_scissors_current_track = tr;