static void trw_layer_draw_track_cb ( const gchar *name, VikTrack *track, struct DrawingParams *dp );
static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct DrawingParams *dp );
+static const gchar* trw_layer_layer_tooltip ( VikTrwLayer *vtl );
+static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, gpointer sublayer );
+
static void goto_coord ( VikLayersPanel *vlp, const VikCoord *coord );
static void trw_layer_goto_track_startpoint ( gpointer pass_along[5] );
static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] );
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] );
static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gboolean is_file_operation );
static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer );
+static void trw_layer_cut_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer );
+
static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len );
static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *item, guint len );
static void trw_layer_free_copied_item ( gint subtype, gpointer item );
(VikLayerFuncSublayerRenameRequest) vik_trw_layer_sublayer_rename_request,
(VikLayerFuncSublayerToggleVisible) vik_trw_layer_sublayer_toggle_visible,
+ (VikLayerFuncSublayerTooltip) trw_layer_sublayer_tooltip,
+ (VikLayerFuncLayerTooltip) trw_layer_layer_tooltip,
(VikLayerFuncMarshall) trw_layer_marshall,
(VikLayerFuncUnmarshall) trw_layer_unmarshall,
(VikLayerFuncWriteFileData) a_gpspoint_write_file,
(VikLayerFuncDeleteItem) trw_layer_del_item,
+ (VikLayerFuncCutItem) trw_layer_cut_item,
(VikLayerFuncCopyItem) trw_layer_copy_item,
(VikLayerFuncPasteItem) trw_layer_paste_item,
(VikLayerFuncFreeCopiedItem) trw_layer_free_copied_item,
trw_layer_delete_item ( pass_along );
}
+static void trw_layer_cut_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer )
+{
+ static gpointer pass_along[5];
+ if (!sublayer) {
+ return;
+ }
+
+ pass_along[0] = vtl;
+ pass_along[1] = NULL;
+ pass_along[2] = GINT_TO_POINTER (subtype);
+ pass_along[3] = sublayer;
+ pass_along[4] = NULL;
+
+ trw_layer_copy_item_cb(pass_along);
+ trw_layer_cut_item_cb(pass_along);
+}
+
static void trw_layer_copy_item_cb( gpointer pass_along[5])
{
VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
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 ) );
gc[9] = vik_viewport_new_gc ( vp, "#96059f", width );
gc[10] = vik_viewport_new_gc ( vp, "#f22ef2", width );
- gc[11] = vik_viewport_new_gc ( vp, "#ff0000", width ); /* above range */
+ gc[11] = vik_viewport_new_gc ( vp, "#874200", width ); /* above range */
gc[12] = vik_viewport_new_gc ( vp, "#000000", width ); /* black / no speed data */
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
#else
- vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, (gint) pass_along[4], NULL, TRUE, TRUE );
+ vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
#endif
*new_iter = *((GtkTreeIter *) pass_along[1]);
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
#else
- vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, (gint) pass_along[4], NULL, TRUE, TRUE );
+ vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
#endif
*new_iter = *((GtkTreeIter *) pass_along[1]);
return TRUE;
}
+// Structure to hold multiple track information for a layer
+typedef struct {
+ gdouble length;
+ time_t start_time;
+ time_t end_time;
+ gint duration;
+} tooltip_tracks;
+
+/*
+ * Build up layer multiple track information via updating the tooltip_tracks structure
+ */
+static void trw_layer_tracks_tooltip ( const gchar *name, VikTrack *tr, tooltip_tracks *tt )
+{
+ tt->length = tt->length + vik_track_get_length (tr);
+
+ // Ensure times are available
+ if ( tr->trackpoints &&
+ VIK_TRACKPOINT(tr->trackpoints->data)->has_timestamp &&
+ VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->has_timestamp ) {
+
+ time_t t1, t2;
+ t1 = VIK_TRACKPOINT(tr->trackpoints->data)->timestamp;
+ t2 = VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp;
+
+ // Assume never actually have a track with a time of 0 (1st Jan 1970)
+ // Hence initialize to the first 'proper' value
+ if ( tt->start_time == 0 )
+ tt->start_time = t1;
+ if ( tt->end_time == 0 )
+ tt->end_time = t2;
+
+ // Update find the earliest / last times
+ if ( t1 < tt->start_time )
+ tt->start_time = t1;
+ if ( t2 > tt->end_time )
+ tt->end_time = t2;
+
+ // Keep track of total time
+ // there maybe gaps within a track (eg segments)
+ // but this should be generally good enough for a simple indicator
+ tt->duration = tt->duration + (int)(t2-t1);
+ }
+}
+
+/*
+ * Generate tooltip text for the layer.
+ * This is relatively complicated as it considers information for
+ * no tracks, a single track or multiple tracks
+ * (which may or may not have timing information)
+ */
+static const gchar* trw_layer_layer_tooltip ( VikTrwLayer *vtl )
+{
+ gchar tbuf1[32];
+ gchar tbuf2[64];
+ gchar tbuf3[64];
+ gchar tbuf4[10];
+ tbuf1[0] = '\0';
+ tbuf2[0] = '\0';
+ tbuf3[0] = '\0';
+ tbuf4[0] = '\0';
+
+ static gchar tmp_buf[128];
+ tmp_buf[0] = '\0';
+
+ // For compact date format I'm using '%x' [The preferred date representation for the current locale without the time.]
+
+ // Safety check - I think these should always be valid
+ if ( vtl->tracks && vtl->waypoints ) {
+ tooltip_tracks tt = { 0.0, 0, 0 };
+ g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_tracks_tooltip, &tt );
+
+ GDate* gdate_start = g_date_new ();
+ g_date_set_time_t (gdate_start, tt.start_time);
+
+ GDate* gdate_end = g_date_new ();
+ g_date_set_time_t (gdate_end, tt.end_time);
+
+ if ( g_date_compare (gdate_start, gdate_end) ) {
+ // Dates differ so print range on separate line
+ g_date_strftime (tbuf1, sizeof(tbuf1), "%x", gdate_start);
+ g_date_strftime (tbuf2, sizeof(tbuf2), "%x", gdate_end);
+ g_snprintf (tbuf3, sizeof(tbuf3), "%s to %s\n", tbuf1, tbuf2);
+ }
+ else {
+ // Same date so just show it and keep rest of text on the same line - provided it's a valid time!
+ if ( tt.start_time != 0 )
+ g_date_strftime (tbuf3, sizeof(tbuf3), "%x: ", gdate_start);
+ }
+
+ tbuf2[0] = '\0';
+ if ( tt.length > 0.0 ) {
+ gdouble len_in_units;
+
+ // 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 = VIK_METERS_TO_MILES(tt.length);
+ }
+ else {
+ g_snprintf (tbuf4, sizeof(tbuf4), "kms");
+ len_in_units = tt.length/1000.0;
+ }
+
+ // Timing information if available
+ tbuf1[0] = '\0';
+ if ( tt.duration > 0 ) {
+ g_snprintf (tbuf1, sizeof(tbuf1),
+ _(" in %d:%02d hrs:mins"),
+ (int)round(tt.duration/3600), (int)round((tt.duration/60)%60));
+ }
+ g_snprintf (tbuf2, sizeof(tbuf2),
+ _("\n%sTotal Length %.1f %s%s"),
+ tbuf3, len_in_units, tbuf4, tbuf1);
+ }
+
+ // Put together all the elements to form compact tooltip text
+ g_snprintf (tmp_buf, sizeof(tmp_buf),
+ _("Tracks: %d - Waypoints: %d%s"),
+ g_hash_table_size (vtl->tracks), g_hash_table_size (vtl->waypoints), tbuf2);
+
+ g_date_free (gdate_start);
+ g_date_free (gdate_end);
+
+ }
+
+ return tmp_buf;
+}
+
+static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, gpointer sublayer )
+{
+ switch ( subtype )
+ {
+ case VIK_TRW_LAYER_SUBLAYER_TRACKS: return NULL;
+ case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: return NULL;
+ case VIK_TRW_LAYER_SUBLAYER_TRACK:
+ {
+ VikTrack *tr = g_hash_table_lookup ( l->tracks, sublayer );
+ if ( tr ) {
+ // Could be a better way of handling strings - but this works...
+ gchar time_buf1[20];
+ gchar time_buf2[20];
+ time_buf1[0] = '\0';
+ time_buf2[0] = '\0';
+ static gchar tmp_buf[100];
+ // Compact info: Short date eg (11/20/99), duration and length
+ // Hopefully these are the things that are most useful and so promoted into the tooltip
+ if ( tr->trackpoints && VIK_TRACKPOINT(tr->trackpoints->data)->has_timestamp ) {
+ // %x The preferred date representation for the current locale without the time.
+ strftime (time_buf1, sizeof(time_buf1), "%x: ", gmtime(&(VIK_TRACKPOINT(tr->trackpoints->data)->timestamp)));
+ if ( VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->has_timestamp ) {
+ gint dur = ( (VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp) - (VIK_TRACKPOINT(tr->trackpoints->data)->timestamp) );
+ if ( dur > 0 )
+ g_snprintf ( time_buf2, sizeof(time_buf2), _("- %d:%02d hrs:mins"), (int)round(dur/3600), (int)round((dur/60)%60) );
+ }
+ }
+ // Get length and consider the appropriate distance units
+ gdouble tr_len = vik_track_get_length(tr);
+ vik_units_distance_t dist_units = a_vik_get_units_distance ();
+ switch (dist_units) {
+ case VIK_UNITS_DISTANCE_KILOMETRES:
+ 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, VIK_METERS_TO_MILES(tr_len), time_buf2);
+ break;
+ default:
+ break;
+ }
+ return tmp_buf;
+ }
+ }
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
+ {
+ VikWaypoint *w = g_hash_table_lookup ( l->waypoints, sublayer );
+ // NB It's OK to return NULL
+ return w->comment;
+ }
+ break;
+ default: break;
+ }
+ return NULL;
+}
+
+
GHashTable *vik_trw_layer_get_tracks ( VikTrwLayer *l )
{
return l->tracks;
}
else
{
- if ( a_dialog_overwrite ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
+ if ( a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
{
gtk_widget_hide ( file_selector );
failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trackname);
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;
}
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
goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &(((VikTrackpoint *) trps->data)->coord));
}
-<<<<<<< HEAD
static void trw_layer_goto_track_max_speed ( gpointer pass_along[5] )
{
VikTrackpoint* vtp = vik_track_get_tp_by_max_speed ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
return 0;
}
+#ifdef VIK_CONFIG_ALPHABETIZED_TRW
+/**
+ * comparison function which can be used to sort tracks or waypoints by name
+ */
+static gint sort_alphabetically (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ const gchar* namea = (const gchar*) a;
+ const gchar* nameb = (const gchar*) b;
+ if ( namea == NULL || nameb == NULL)
+ return 0;
+ else
+ // Same sort method as used in the vik_treeview_*_alphabetize functions
+ return strcmp ( namea, nameb );
+}
+#endif
+
static void trw_layer_merge_with_other ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
return;
}
+#ifdef VIK_CONFIG_ALPHABETIZED_TRW
+ // Sort alphabetically for user presentation
+ tracks_with_timestamp = g_list_sort_with_data (tracks_with_timestamp, sort_alphabetically, NULL);
+#endif
+
GList *merge_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
- vtl->tracks, tracks_with_timestamp, TRUE,
+ tracks_with_timestamp, TRUE,
_("Merge with..."), _("Select track to merge with"));
g_list_free(tracks_with_timestamp);
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 */
if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
{
+ gboolean separator_created = FALSE;
+
/* could be a right-click using the tool */
if ( vlp != NULL ) {
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
+ separator_created = TRUE;
+
item = gtk_menu_item_new_with_mnemonic ( _("_Goto") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_waypoint), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
if ( is_valid_geocache_name ( (gchar *) sublayer ) )
{
+ if ( !separator_created ) {
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
item = gtk_menu_item_new_with_mnemonic ( _("_Visit Geocache Webpage") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoint_gc_webpage), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
}
}
+ 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);
+ gtk_widget_show ( item );
+ }
+
if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
{
GtkWidget *goto_submenu;
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 );
}
}
- if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
- {
- item = gtk_menu_item_new ();
- gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
- gtk_widget_show ( item );
-
- 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);
- gtk_widget_show ( item );
- }
-
return rv;
}
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 ();
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() );
*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 )
{
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 );
}
}