]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Add the storage and retrieval of any kind of track or waypoint selected item (either...
[andy/viking.git] / src / viktrwlayer.c
index a1ada99513cbfa0267dab719cce57cc0fd5b9a75..5f7342a1103917c66aab1ac2d5e38d8f3abb0019 100644 (file)
@@ -236,6 +236,7 @@ static void trw_layer_goto_track_min_alt ( gpointer pass_along[5] );
 static void trw_layer_auto_track_view ( gpointer pass_along[5] );
 static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] );
 static void trw_layer_split_by_timestamp ( gpointer pass_along[6] );
+static void trw_layer_split_by_n_points ( gpointer pass_along[6] );
 static void trw_layer_download_map_along_track_cb(gpointer pass_along[6]);
 static void trw_layer_centerize ( gpointer layer_and_vlp[2] );
 static void trw_layer_auto_view ( gpointer layer_and_vlp[2] );
@@ -941,7 +942,7 @@ void vik_trw_layer_free ( VikTrwLayer *trwlayer )
   trw_layer_free_track_gcs ( trwlayer );
 
   if ( trwlayer->wp_right_click_menu )
-    gtk_object_sink ( GTK_OBJECT(trwlayer->wp_right_click_menu) );
+    g_object_ref_sink ( G_OBJECT(trwlayer->wp_right_click_menu) );
 
   if ( trwlayer->wplabellayout != NULL)
     g_object_unref ( G_OBJECT ( trwlayer->wplabellayout ) );
@@ -1639,7 +1640,7 @@ static const gchar* trw_layer_layer_tooltip ( VikTrwLayer *vtl )
       // Setup info dependent on distance units
       if ( a_vik_get_units_distance() == VIK_UNITS_DISTANCE_MILES ) {
        g_snprintf (tbuf4, sizeof(tbuf4), "miles");
-       len_in_units = tt.length/1600.0;
+       len_in_units = VIK_METERS_TO_MILES(tt.length);
       }
       else {
        g_snprintf (tbuf4, sizeof(tbuf4), "kms");
@@ -1706,7 +1707,7 @@ static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, g
          g_snprintf (tmp_buf, sizeof(tmp_buf), _("%s%.1f km %s"), time_buf1, tr_len/1000.0, time_buf2);
          break;
        case VIK_UNITS_DISTANCE_MILES:
-         g_snprintf (tmp_buf, sizeof(tmp_buf), _("%s%.1f miles %s"), time_buf1, tr_len/1600.0, time_buf2);
+         g_snprintf (tmp_buf, sizeof(tmp_buf), _("%s%.1f miles %s"), time_buf1, VIK_METERS_TO_MILES(tr_len), time_buf2);
          break;
        default:
          break;
@@ -2020,16 +2021,20 @@ static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
 
 gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikCoord *def_coord )
 {
-  gchar *name = highest_wp_number_get(vtl);
+  gchar *default_name = highest_wp_number_get(vtl);
   VikWaypoint *wp = vik_waypoint_new();
+  gchar *returned_name;
+  gboolean updated;
   wp->coord = *def_coord;
 
-  if ( a_dialog_new_waypoint ( w, &name, wp, vik_trw_layer_get_waypoints ( vtl ), vtl->coord_mode ) )
+  if ( ( returned_name = a_dialog_waypoint ( w, default_name, wp, vik_trw_layer_get_waypoints ( vtl ), vtl->coord_mode, TRUE, &updated ) ) )
   {
     wp->visible = TRUE;
-    vik_trw_layer_add_waypoint ( vtl, name, wp );
+    vik_trw_layer_add_waypoint ( vtl, returned_name, wp );
+    g_free (default_name);
     return TRUE;
   }
+  g_free (default_name);
   vik_waypoint_free(wp);
   return FALSE;
 }
@@ -2508,10 +2513,11 @@ static void trw_layer_properties_item ( gpointer pass_along[5] )
     VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] );
     if ( wp )
     {
-      if ( a_dialog_new_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), NULL, wp, NULL, vtl->coord_mode ) )
+      gboolean updated = FALSE;
+      a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), pass_along[3], wp, NULL, vtl->coord_mode, FALSE, &updated );
 
-      if ( VIK_LAYER(vtl)->visible )
-        vik_layer_emit_update ( VIK_LAYER(vtl) );
+      if ( updated && VIK_LAYER(vtl)->visible )
+       vik_layer_emit_update ( VIK_LAYER(vtl) );
     }
   }
   else
@@ -2986,6 +2992,81 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] )
   vik_layer_emit_update(VIK_LAYER(pass_along[0]));
 }
 
+/**
+ * Split a track by the number of points as specified by the user
+ */
+static void trw_layer_split_by_n_points ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *track = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+  // Check valid track
+  GList *trps = track->trackpoints;
+  if ( !trps )
+    return;
+
+  gint points = a_dialog_get_positive_number(VIK_GTK_WINDOW_FROM_LAYER(pass_along[0]),
+                                            _("Split Every Nth Point"),
+                                            _("Split on every Nth point:"),
+                                            250,   // Default value as per typical limited track capacity of various GPS devices
+                                            2,     // Min
+                                            65536, // Max
+                                            5);    // Step
+  // Was a valid number returned?
+  if (!points)
+    return;
+
+  // Now split...
+  GList *iter;
+  GList *newlists = NULL;
+  GList *newtps = NULL;
+  gint count = 0;
+  iter = trps;
+
+  while (iter) {
+    /* accumulate trackpoint copies in newtps, in reverse order */
+    newtps = g_list_prepend(newtps, vik_trackpoint_copy(VIK_TRACKPOINT(iter->data)));
+    count++;
+    if (count >= points) {
+      /* flush accumulated trackpoints into new list */
+      newlists = g_list_append(newlists, g_list_reverse(newtps));
+      newtps = NULL;
+      count = 0;
+    }
+    iter = g_list_next(iter);
+  }
+
+  // If there is a remaining chunk put that into the new split list
+  // This may well be the whole track if no split points were encountered
+  if (newtps) {
+      newlists = g_list_append(newlists, g_list_reverse(newtps));
+  }
+
+  /* put lists of trackpoints into tracks */
+  iter = newlists;
+  guint i = 1;
+  // Only bother updating if the split results in new tracks
+  if (g_list_length (newlists) > 1) {
+    while (iter) {
+      gchar *new_tr_name;
+      VikTrack *tr;
+
+      tr = vik_track_new();
+      tr->visible = track->visible;
+      tr->trackpoints = (GList *)(iter->data);
+
+      new_tr_name = g_strdup_printf("%s #%d", (gchar *) pass_along[3], i++);
+      vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), new_tr_name, tr);
+
+      iter = g_list_next(iter);
+    }
+    // Remove original track and then update the display
+    vik_trw_layer_delete_track(VIK_TRW_LAYER(pass_along[0]), (gchar *)pass_along[3]);
+    vik_layer_emit_update(VIK_LAYER(pass_along[0]));
+  }
+  g_list_free(newlists);
+}
+
 /* end of split/merge routines */
 
 
@@ -3212,6 +3293,7 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
   if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
   {
+    rv = TRUE;
     item = gtk_menu_item_new_with_mnemonic ( _("_New Waypoint") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wp), pass_along );
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
@@ -3281,6 +3363,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_mnemonic ( _("Split By _Number of Points") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_n_points), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_widget_show ( item );
+
     item = gtk_menu_item_new_with_mnemonic ( _("Down_load Maps Along Track...") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_download_map_along_track_cb), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
@@ -3427,8 +3514,8 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
     trw_layer_cancel_current_tp ( vtl, TRUE );
   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, NULL ) ) )
+    gchar *name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, vtl->current_tp_track_name);
+    if ( ( name = a_dialog_new_track ( GTK_WINDOW(vtl->tpwin), vtl->tracks, name ) ) )
     {
       VikTrack *tr = vik_track_new ();
       GList *newglist = g_list_alloc ();
@@ -3867,7 +3954,7 @@ static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *e
   if ( event->button == 3 && vtl->waypoint_rightclick )
   {
     if ( vtl->wp_right_click_menu )
-      gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) );
+      g_object_ref_sink ( G_OBJECT(vtl->wp_right_click_menu) );
     vtl->wp_right_click_menu = GTK_MENU ( gtk_menu_new () );
     vik_trw_layer_sublayer_add_menu_items ( vtl, vtl->wp_right_click_menu, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, vtl->current_wp_name, g_hash_table_lookup ( vtl->waypoints_iters, vtl->current_wp_name  ) );
     gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
@@ -4360,24 +4447,42 @@ static void image_wp_make_list ( char *name, VikWaypoint *wp, GSList **pics )
     *pics = g_slist_append ( *pics, (gpointer) g_strdup ( wp->image ) );
 }
 
-static void create_thumbnails_thread ( GSList *pics, gpointer threaddata )
+/* Structure for thumbnail creating data used in the background thread */
+typedef struct {
+  VikTrwLayer *vtl; // Layer needed for redrawing
+  GSList *pics;     // Image list
+} thumbnail_create_thread_data;
+
+static int create_thumbnails_thread ( thumbnail_create_thread_data *tctd, gpointer threaddata )
 {
-  guint total = g_slist_length(pics), done = 0;
-  while ( pics )
+  guint total = g_slist_length(tctd->pics), done = 0;
+  while ( tctd->pics )
   {
-    a_thumbnails_create ( (gchar *) pics->data );
-    a_background_thread_progress ( threaddata, ((gdouble) ++done) / total );
-    pics = pics->next;
+    a_thumbnails_create ( (gchar *) tctd->pics->data );
+    int result = a_background_thread_progress ( threaddata, ((gdouble) ++done) / total );
+    if ( result != 0 )
+      return -1; /* Abort thread */
+
+    tctd->pics = tctd->pics->next;
   }
+
+  // Redraw to show the thumbnails as they are now created
+  gdk_threads_enter();
+  if ( IS_VIK_LAYER(tctd->vtl) )
+    vik_layer_emit_update ( VIK_LAYER(tctd->vtl) );
+  gdk_threads_leave();
+
+  return 0;
 }
 
-static void free_pics_slist ( GSList *pics )
+static void thumbnail_create_thread_free ( thumbnail_create_thread_data *tctd )
 {
-  while ( pics )
+  while ( tctd->pics )
   {
-    g_free ( pics->data );
-    pics = g_slist_delete_link ( pics, pics );
+    g_free ( tctd->pics->data );
+    tctd->pics = g_slist_delete_link ( tctd->pics, tctd->pics );
   }
+  g_free ( tctd );
 }
 
 static void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp )
@@ -4390,7 +4495,16 @@ static void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp )
     {
       gint len = g_slist_length ( pics );
       gchar *tmp = g_strdup_printf ( _("Creating %d Image Thumbnails..."), len );
-      a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vtl), tmp, (vik_thr_func) create_thumbnails_thread, pics, (vik_thr_free_func) free_pics_slist, NULL, len );
+      thumbnail_create_thread_data *tctd = g_malloc ( sizeof(thumbnail_create_thread_data) );
+      tctd->vtl = vtl;
+      tctd->pics = pics;
+      a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           tmp,
+                           (vik_thr_func) create_thumbnails_thread,
+                           tctd,
+                           (vik_thr_free_func) thumbnail_create_thread_free,
+                           NULL,
+                           len );
       g_free ( tmp );
     }
   }