X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/4258f4e221ef2abaa1e078e44abd630da49729be..158b364252ddd227db2d9e047b98547e4e0048ed:/src/viktrwlayer.c?ds=sidebyside diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 9a37d516..944b5a37 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -30,7 +30,6 @@ #include "viking.h" #include "vikmapslayer.h" -#include "viktrwlayer_pixmap.h" #include "viktrwlayer_tpwin.h" #include "viktrwlayer_propwin.h" #include "garminsymbols.h" @@ -40,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 @@ -49,12 +48,21 @@ #include "icons/icons.h" +#ifdef HAVE_MATH_H #include +#endif +#ifdef HAVE_STRING_H #include +#endif +#ifdef HAVE_STDLIB_H #include +#endif +#include #include #include +#include +#include #include /* Relax some dependencies */ @@ -63,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 "(wget -O - \"http://maps.google.com/maps?q=%f,%f to %f,%f&output=js\" 2>/dev/null)" +#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 @@ -204,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 ); @@ -222,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] ); @@ -234,10 +246,10 @@ 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 ); +static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation ); +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_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len ); @@ -252,19 +264,19 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl ); static gpointer tool_edit_trackpoint_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); -static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); +static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data ); static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); static gpointer tool_edit_waypoint_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); -static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); +static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data ); static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); static gpointer tool_begin_track_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); -static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); +static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp ); static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ); static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); @@ -272,8 +284,6 @@ static gpointer tool_magic_scissors_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); -static gboolean uppercase_exists_in_hash ( GHashTable *hash, const gchar *str ); - static void cached_pixbuf_free ( CachedPixbuf *cp ); static gint cached_pixbuf_cmp ( CachedPixbuf *cp, const gchar *name ); static void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp ); @@ -295,30 +305,30 @@ static void highest_wp_number_remove_wp(VikTrwLayer *vtl, const gchar *old_wp_na static VikToolInterface trw_layer_tools[] = { { N_("Create Waypoint"), (VikToolConstructorFunc) tool_new_waypoint_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_new_waypoint_click, NULL, NULL, (VikToolKeyFunc) NULL, &cursor_addwp }, + (VikToolMouseFunc) tool_new_waypoint_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf }, { N_("Create Track"), (VikToolConstructorFunc) tool_new_track_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_new_track_click, (VikToolMouseFunc) tool_new_track_move, NULL, - (VikToolKeyFunc) tool_new_track_key_press, &cursor_addtr }, + (VikToolMouseFunc) tool_new_track_click, (VikToolMouseMoveFunc) tool_new_track_move, NULL, + (VikToolKeyFunc) tool_new_track_key_press, GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf }, { N_("Begin Track"), (VikToolConstructorFunc) tool_begin_track_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_begin_track_click, NULL, NULL, (VikToolKeyFunc) NULL, &cursor_begintr }, + (VikToolMouseFunc) tool_begin_track_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf }, { N_("Edit Waypoint"), (VikToolConstructorFunc) tool_edit_waypoint_create, NULL, NULL, NULL, (VikToolMouseFunc) tool_edit_waypoint_click, - (VikToolMouseFunc) tool_edit_waypoint_move, - (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, &cursor_edwp }, + (VikToolMouseMoveFunc) tool_edit_waypoint_move, + (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf }, { N_("Edit Trackpoint"), (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL, (VikToolMouseFunc) tool_edit_trackpoint_click, - (VikToolMouseFunc) tool_edit_trackpoint_move, - (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, &cursor_edtr }, + (VikToolMouseMoveFunc) tool_edit_trackpoint_move, + (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf }, { N_("Show Picture"), (VikToolConstructorFunc) tool_show_picture_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_show_picture_click, NULL, NULL, (VikToolKeyFunc) NULL, &cursor_showpic }, + (VikToolMouseFunc) tool_show_picture_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf }, { N_("Magic Scissors"), (VikToolConstructorFunc) tool_magic_scissors_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_magic_scissors_click, NULL, NULL, (VikToolKeyFunc) NULL, &cursor_iscissors }, + (VikToolMouseFunc) tool_magic_scissors_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_iscissors_pixbuf }, }; enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS }; @@ -391,7 +401,7 @@ enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PAR VikLayerInterface vik_trw_layer_interface = { "TrackWaypoint", - &trwlayer_pixbuf, + &viktrwlayer_pixbuf, trw_layer_tools, sizeof(trw_layer_tools) / sizeof(VikToolInterface), @@ -479,7 +489,7 @@ static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublay pass_along[0] = vtl; pass_along[1] = NULL; - pass_along[2] = (gpointer) subtype; + pass_along[2] = GINT_TO_POINTER (subtype); pass_along[3] = sublayer; pass_along[4] = NULL; @@ -489,7 +499,7 @@ static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublay static void trw_layer_copy_item_cb( gpointer pass_along[5]) { VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); - gint subtype = (gint)pass_along[2]; + gint subtype = GPOINTER_TO_INT (pass_along[2]); gpointer * sublayer = pass_along[3]; guint8 *data = NULL; guint len; @@ -570,7 +580,7 @@ static void trw_layer_free_copied_item ( gint subtype, gpointer item ) } } -static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp ) +static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation ) { switch ( 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 ); @@ -628,7 +638,7 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara return TRUE; } -static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id ) +static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gboolean is_file_operation ) { VikLayerParamData rv; switch ( id ) @@ -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; @@ -676,7 +688,8 @@ static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len ) a_gpx_write_file(vtl, f); vik_layer_marshall_params(VIK_LAYER(vtl), &pd, &pl); fclose(f); - g_file_get_contents(tmpname, (void *)&dd, (void *)&dl, NULL); + f = NULL; + g_file_get_contents(tmpname, &dd, &dl, NULL); *len = sizeof(pl) + pl + dl; *data = g_malloc(*len); memcpy(*data, &pl, sizeof(pl)); @@ -685,15 +698,15 @@ static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len ) g_free(pd); g_free(dd); - remove(tmpname); + g_remove(tmpname); g_free(tmpname); } } -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; @@ -711,34 +724,62 @@ static VikTrwLayer *trw_layer_unmarshall( gpointer data, gint len, VikViewport * rewind(f); a_gpx_read_file(rv, f); fclose(f); - remove(tmpname); + f = NULL; + g_remove(tmpname); g_free(tmpname); return rv; } -static GList * a_array_to_glist(gpointer data[]) +static GList * str_array_to_glist(gchar* data[]) { GList *gl = NULL; gpointer * p; - for (p = data; *p; p++) + for (p = (gpointer)data; *p; p++) gl = g_list_prepend(gl, *p); return(g_list_reverse(gl)); } +static gboolean strcase_equal(gconstpointer s1, gconstpointer s2) +{ + return (strcasecmp(s1, s2) == 0); +} + +static guint strcase_hash(gconstpointer v) +{ + /* 31 bit hash function */ + int i; + const gchar *t = v; + gchar s[128]; /* malloc is too slow for reading big files */ + gchar *p = s; + + for (i = 0; (i < (sizeof(s)- 1)) && t[i]; i++) + p[i] = toupper(t[i]); + p[i] = '\0'; + + p = s; + guint32 h = *p; + if (h) { + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + *p; + } + + return h; +} + VikTrwLayer *vik_trw_layer_new ( gint drawmode ) { if (trw_layer_params[PARAM_DM].widget_data == NULL) - trw_layer_params[PARAM_DM].widget_data = a_array_to_glist(params_drawmodes); + trw_layer_params[PARAM_DM].widget_data = str_array_to_glist(params_drawmodes); if (trw_layer_params[PARAM_WPSYM].widget_data == NULL) - trw_layer_params[PARAM_WPSYM].widget_data = a_array_to_glist(params_wpsymbols); + trw_layer_params[PARAM_WPSYM].widget_data = str_array_to_glist(params_wpsymbols); VikTrwLayer *rv = VIK_TRW_LAYER ( g_object_new ( VIK_TRW_LAYER_TYPE, NULL ) ); vik_layer_init ( VIK_LAYER(rv), VIK_LAYER_TRW ); - rv->waypoints = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) vik_waypoint_free ); + rv->waypoints = g_hash_table_new_full ( strcase_hash, strcase_equal, g_free, (GDestroyNotify) vik_waypoint_free ); rv->tracks = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) vik_track_free ); rv->tracks_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free ); - rv->waypoints_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free ); + rv->waypoints_iters = g_hash_table_new_full ( strcase_hash, strcase_equal, NULL, g_free ); /* TODO: constants at top */ rv->waypoints_visible = rv->tracks_visible = TRUE; @@ -927,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 @@ -949,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); @@ -988,8 +1029,10 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr if ( drawpoints && dp->vtl->coord_mode == VIK_COORD_UTM && tp->coord.utm_zone != dp->center->utm_zone ) draw_utm_skip_insignia ( dp->vp, main_gc, x, y); - if ( dp->vtl->drawmode == DRAWMODE_BY_VELOCITY ) + if ( dp->vtl->drawmode == DRAWMODE_BY_VELOCITY ) { dp->track_gc_iter = calculate_velocity ( dp->vtl, tp, tp2 ); + main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter); + } if (!useoldvals) vik_viewport_coord_to_screen ( dp->vp, &(tp2->coord), &oldx, &oldy ); @@ -1036,8 +1079,10 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr if ( dp->vtl->coord_mode != VIK_COORD_UTM || tp->coord.utm_zone == dp->center->utm_zone ) { vik_viewport_coord_to_screen ( dp->vp, &(tp->coord), &x, &y ); - if ( dp->vtl->drawmode == DRAWMODE_BY_VELOCITY ) + if ( dp->vtl->drawmode == DRAWMODE_BY_VELOCITY ) { dp->track_gc_iter = calculate_velocity ( dp->vtl, tp, tp2 ); + main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter); + } if ( drawing_white_background ) vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y); @@ -1084,7 +1129,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 */ @@ -1182,11 +1227,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 ); } } } @@ -1305,7 +1357,7 @@ static void trw_layer_realize_track ( gchar *name, VikTrack *track, gpointer pas GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter)); #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, (gint) pass_along[4], NULL, TRUE, TRUE ); + 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 ); #endif @@ -1321,7 +1373,7 @@ static void trw_layer_realize_waypoint ( gchar *name, VikWaypoint *wp, gpointer { GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter)); #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, (gint) pass_along[4], NULL, TRUE, TRUE ); + 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 ); #endif @@ -1435,13 +1487,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 @@ -1466,13 +1549,18 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type ) GtkWidget *file_selector; const gchar *fn; gboolean failed = FALSE; - file_selector = gtk_file_selection_new (_("Export Layer")); - gtk_file_selection_set_filename (GTK_FILE_SELECTION(file_selector), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0]))); - - while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_OK ) + file_selector = gtk_file_chooser_dialog_new (_("Export Layer"), + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + 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 ) { - fn = gtk_file_selection_get_filename (GTK_FILE_SELECTION(file_selector) ); - if ( access ( fn, F_OK ) != 0 ) + fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_selector) ); + if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE ) { gtk_widget_hide ( file_selector ); failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type ); @@ -1480,7 +1568,7 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type ) } else { - if ( a_dialog_overwrite ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) ) + if ( a_dialog_overwrite ( 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 ); @@ -1511,7 +1599,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, @@ -1561,7 +1649,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 ) ) { @@ -1573,6 +1660,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]); @@ -1588,6 +1718,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; @@ -1631,6 +1762,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 ); @@ -1692,9 +1841,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 ); @@ -1708,21 +1857,6 @@ void vik_trw_layer_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t ) } -static gboolean uppercase_exists_in_hash ( GHashTable *hash, const gchar *str ) -{ - gchar *upp = g_strdup ( str ); - gboolean rv; - char *tmp = upp; - while ( *tmp ) - { - *tmp = toupper(*tmp); - tmp++; - } - rv = g_hash_table_lookup ( hash, upp ) ? TRUE : FALSE; - g_free (upp); - return rv; -} - /* to be called whenever a track has been deleted or may have been changed. */ void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, const gchar *trk_name ) { @@ -1924,7 +2058,7 @@ static void trw_layer_delete_item ( gpointer pass_along[5] ) { VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); gboolean was_visible = FALSE; - if ( (gint) pass_along[2] == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) + if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) { was_visible = vik_trw_layer_delete_waypoint ( vtl, (gchar *) pass_along[3] ); } @@ -1940,7 +2074,7 @@ static void trw_layer_delete_item ( gpointer pass_along[5] ) static void trw_layer_properties_item ( gpointer pass_along[5] ) { VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); - if ( (gint) pass_along[2] == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) + if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) { VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] ); if ( wp ) @@ -1999,12 +2133,30 @@ static void trw_layer_extend_track_end ( gpointer pass_along[6] ) VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ); vtl->current_track = track; - vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK ); + vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK); if ( track->trackpoints ) goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) ); } +/** + * extend a track using magic scissors + */ +static void trw_layer_extend_track_end_ms ( gpointer pass_along[6] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); + VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ); + VikCoord last_coord = (((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord); + + vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, NUM_TOOLS ); + vtl->magic_scissors_coord = last_coord; + vtl->magic_scissors_current_track = track; + + if ( track->trackpoints ) + goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &last_coord) ; + +} + static void trw_layer_apply_dem_data ( gpointer pass_along[6] ) { /* TODO: check & warn if no DEM data, or no applicable DEM data. */ @@ -2028,6 +2180,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] */ @@ -2038,7 +2223,7 @@ static void find_nearby_track(gpointer key, gpointer value, gpointer user_data) GList **nearby_tracks = ((gpointer *)user_data)[0]; GList *orig_track = ((gpointer *)user_data)[1]; - guint thr = (guint)((gpointer *)user_data)[2]; + guint thr = GPOINTER_TO_UINT (((gpointer *)user_data)[2]); /* outline: * detect reasons for not merging, and return @@ -2098,6 +2283,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] ) { @@ -2115,6 +2352,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; } @@ -2140,7 +2378,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] ) /* g_print("Original track times: %d and %d\n", t1, t2); */ params[0] = &nearby_tracks; params[1] = trps; - params[2] = (gpointer)thr; + params[2] = GUINT_TO_POINTER (thr); /* get a list of adjacent-in-time tracks */ g_hash_table_foreach(vtl->tracks, find_nearby_track, (gpointer)params); @@ -2184,7 +2422,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] ) } while (track_count > 1); g_list_free(nearby_tracks); free(orig_track_name); - vik_layer_emit_update(vtl); + vik_layer_emit_update( VIK_LAYER(vtl) ); } /* split by time routine */ @@ -2279,17 +2517,18 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar { if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) { - int i; gchar *rv; VikWaypoint *wp; - if ( strcasecmp ( newname, sublayer ) == 0 ) + if (strcmp(newname, sublayer) == 0 ) return NULL; - if ( uppercase_exists_in_hash ( l->waypoints, newname ) ) - { - a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Waypoint Already Exists") ); - return NULL; + if (strcasecmp(newname, sublayer)) { /* Not just changing case */ + if (g_hash_table_lookup( l->waypoints, newname)) + { + a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Waypoint Already Exists") ); + return NULL; + } } iter = g_hash_table_lookup ( l->waypoints_iters, sublayer ); @@ -2300,8 +2539,6 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar g_hash_table_remove ( l->waypoints, sublayer ); rv = g_strdup(newname); - for ( i = strlen(rv) - 1; i >= 0; i-- ) - rv[i] = toupper(rv[i]); vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv ); @@ -2319,19 +2556,20 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar } if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) { - int i; gchar *rv; VikTrack *tr; GtkTreeIter *iter; gchar *orig_key; - if ( strcasecmp ( newname, sublayer ) == 0 ) + if (strcmp(newname, sublayer) == 0) return NULL; - if ( uppercase_exists_in_hash ( l->tracks, newname ) ) - { - a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Track Already Exists") ); - return NULL; + if (strcasecmp(newname, sublayer)) { /* Not just changing case */ + if (g_hash_table_lookup( l->tracks, newname)) + { + a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Track Already Exists") ); + return NULL; + } } g_hash_table_lookup_extended ( l->tracks, sublayer, (void *)&orig_key, (void *)&tr ); @@ -2341,8 +2579,6 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar g_hash_table_steal ( l->tracks_iters, sublayer ); rv = g_strdup(newname); - for ( i = strlen(rv) - 1; i >= 0; i-- ) - rv[i] = toupper(rv[i]); vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv ); @@ -2413,7 +2649,7 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, pass_along[0] = l; pass_along[1] = vlp; - pass_along[2] = (gpointer) subtype; + pass_along[2] = GINT_TO_POINTER (subtype); pass_along[3] = sublayer; staticiter = *iter; /* will exist after function has ended */ pass_along[4] = &staticiter; @@ -2496,6 +2732,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 ); @@ -2511,11 +2752,16 @@ 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 ( "Extend track end" ); + item = gtk_menu_item_new_with_label ( _("Extend track end") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); + item = gtk_menu_item_new_with_label ( _("Extend using magic scissors") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_ms), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); + gtk_widget_show ( item ); + #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_track_cb), pass_along ); @@ -2525,13 +2771,13 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, if ( is_valid_google_route ( l, (gchar *) sublayer ) ) { - item = gtk_menu_item_new_with_label ( "View Google Directions" ); + item = gtk_menu_item_new_with_label ( _("View Google Directions") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_google_route_webpage), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); } - item = gtk_menu_item_new_with_label ( "Use with filter" ); + item = gtk_menu_item_new_with_label ( _("Use with filter") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_use_with_filter), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); @@ -2598,7 +2844,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 (); @@ -2615,6 +2861,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)); } @@ -2892,6 +3140,9 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve return TRUE; } + if ( !vtl->vl.visible || !vtl->waypoints_visible ) + return FALSE; + if ( vtl->current_wp && vtl->current_wp->visible ) { /* first check if current WP is within area (other may be 'closer', but we want to move the current) */ @@ -2949,7 +3200,7 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve return FALSE; } -static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ) +static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data ) { tool_ed_t *t = data; VikViewport *vvp = t->vvp; @@ -3074,7 +3325,7 @@ static gboolean ct_sync ( gpointer passalong ) return FALSE; } -static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) +static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp ) { /* if we haven't sync'ed yet, we don't have time to do more. */ if ( vtl->ct_sync_done && vtl->current_track && vtl->current_track->trackpoints ) { @@ -3162,8 +3413,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; @@ -3189,7 +3440,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; @@ -3255,6 +3505,9 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e if (!vtl || vtl->vl.type != VIK_LAYER_TRW) return FALSE; + if ( !vtl->vl.visible || !vtl->tracks_visible ) + return FALSE; + if ( vtl->current_tpl ) { /* first check if it is within range of prev. tp. and if current_tp track is shown. (if it is, we are moving that trackpoint.) */ @@ -3292,7 +3545,7 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e return FALSE; } -static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ) +static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data ) { tool_ed_t *t = data; VikViewport *vvp = t->vvp; @@ -3393,11 +3646,12 @@ static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *ev } else if ( vtl->magic_scissors_started || (event->state & GDK_CONTROL_MASK && vtl->magic_scissors_current_track) ) { struct LatLon start, end; - gchar *cmd; + gchar startlat[G_ASCII_DTOSTR_BUF_SIZE], startlon[G_ASCII_DTOSTR_BUF_SIZE]; + gchar endlat[G_ASCII_DTOSTR_BUF_SIZE], endlon[G_ASCII_DTOSTR_BUF_SIZE]; + gchar *url; vik_coord_to_latlon ( &(vtl->magic_scissors_coord), &start ); vik_coord_to_latlon ( &(tmp), &end ); - cmd = g_strdup_printf(GOOGLE_DIRECTIONS_STRING, start.lat, start.lon, end.lat, end.lon ); vtl->magic_scissors_coord = tmp; /* for continuations */ /* these are checked when adding a track from a file (vik_trw_layer_filein_add_track) */ @@ -3408,8 +3662,13 @@ static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *ev vtl->magic_scissors_started = FALSE; } - a_babel_convert_from_shellcommand ( vtl, cmd, "google", NULL, NULL ); - g_free ( cmd ); + url = g_strdup_printf(GOOGLE_DIRECTIONS_STRING, + g_ascii_dtostr (startlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lat), + 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, "kml", NULL, NULL ); + g_free ( url ); /* see if anything was done -- a track was added or appended to */ if ( vtl->magic_scissors_check_added_track && vtl->magic_scissors_added_track_name ) { @@ -3418,7 +3677,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; @@ -3700,17 +3959,22 @@ void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, g new_map = TRUE; } - /* fill-ins for far apart points */ - GList *cur_rect, *next_rect; GList *fillins = NULL; - for (cur_rect = rects_to_download; - (next_rect = cur_rect->next) != NULL; - cur_rect = cur_rect->next) { - if ((wh.lon < ABS(GLRECT(cur_rect)->center.east_west - GLRECT(next_rect)->center.east_west)) || - (wh.lat < ABS(GLRECT(cur_rect)->center.north_south - GLRECT(next_rect)->center.north_south))) { - fillins = add_fillins(fillins, &GLRECT(cur_rect)->center, &GLRECT(next_rect)->center, &wh); + /* 'fillin' doesn't work in UTM mode - potentially ending up in massive loop continually allocating memory - hence don't do it */ + /* seems that ATM the function get_next_coord works only for LATLON */ + if ( cur_coord->mode == VIK_COORD_LATLON ) { + /* fill-ins for far apart points */ + GList *cur_rect, *next_rect; + for (cur_rect = rects_to_download; + (next_rect = cur_rect->next) != NULL; + cur_rect = cur_rect->next) { + if ((wh.lon < ABS(GLRECT(cur_rect)->center.east_west - GLRECT(next_rect)->center.east_west)) || + (wh.lat < ABS(GLRECT(cur_rect)->center.north_south - GLRECT(next_rect)->center.north_south))) { + fillins = add_fillins(fillins, &GLRECT(cur_rect)->center, &GLRECT(next_rect)->center, &wh); + } } - } + } else + g_message("%s: this feature works only in Mercator mode", __FUNCTION__); if (fillins) { GList *iter = fillins;