/* WARNING: If you go beyond this point, we are NOT responsible for any ill effects on your sanity */
/* viktrwlayer.c -- 2200 lines can make a difference in the state of things */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "viking.h"
-#include "viktrwlayer_pixmap.h"
+#include "vikmapslayer.h"
#include "viktrwlayer_tpwin.h"
#include "viktrwlayer_propwin.h"
#include "garminsymbols.h"
#include "thumbnails.h"
#include "background.h"
#include "gpx.h"
+#include "babel.h"
+#include "dem.h"
+#include "dems.h"
+#include "geonamessearch.h"
+#ifdef VIK_CONFIG_OPENSTREETMAP
+#include "osm-traces.h"
+#endif
+#include "acquire.h"
+#include "util.h"
+
+#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>
+#include <gdk/gdkkeysyms.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+
+/* Relax some dependencies */
+#if ! GLIB_CHECK_VERSION(2,12,0)
+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=kml"
#define VIK_TRW_LAYER_TRACK_GC 13
#define VIK_TRW_LAYER_TRACK_GC_RATES 10
#define VIK_TRW_LAYER_TRACK_GC_MIN 0
gdouble velocity_min, velocity_max;
GArray *track_gc;
guint16 track_gc_iter;
+ GdkGC *current_track_gc;
GdkGC *track_bg_gc;
GdkGC *waypoint_gc;
GdkGC *waypoint_text_gc;
GdkFont *waypoint_font;
VikTrack *current_track;
guint16 ct_x1, ct_y1, ct_x2, ct_y2;
+ gboolean ct_sync_done;
+
VikCoordMode coord_mode;
/* track editing tool -- more specifically, moving tps */
gboolean moving_tp;
+ /* magic scissors tool */
+ gboolean magic_scissors_started;
+ VikCoord magic_scissors_coord;
+ gboolean magic_scissors_check_added_track;
+ gchar *magic_scissors_added_track_name;
+ VikTrack *magic_scissors_current_track;
+ gboolean magic_scissors_append;
+
gboolean drawlabels;
gboolean drawimages;
guint8 image_alpha;
/* menu */
VikStdLayerMenuItem menu_selection;
+ gint highest_wp_number;
};
/* A caached waypoint image. */
gdouble ce1, ce2, cn1, cn2;
};
-static vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16);
+static void vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16);
static guint16 vik_trw_layer_get_menu_selection(VikTrwLayer *vtl);
static void trw_layer_delete_item ( gpointer *pass_along );
+static void trw_layer_copy_item_cb( gpointer *pass_along);
+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 );
static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] );
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_download_map_along_track_cb(gpointer pass_along[6]);
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] );
static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp );
-static VikTrwLayer *trw_layer_copy ( VikTrwLayer *vtl, gpointer 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 void trw_layer_free_copied_item ( gint subtype, gpointer item );
static void trw_layer_drag_drop_request ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, GtkTreeIter *src_item_iter, GtkTreePath *dest_path );
-static void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, const gchar *trk_name );
static void trw_layer_cancel_last_tp ( VikTrwLayer *vtl );
static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy );
static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response );
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, 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 );
+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 waypoint_convert ( const gchar *name, VikWaypoint *wp, VikCoordMode *dest_mode );
static void track_convert ( const gchar *name, VikTrack *tr, VikCoordMode *dest_mode );
+static gchar *highest_wp_number_get(VikTrwLayer *vtl);
+static void highest_wp_number_reset(VikTrwLayer *vtl);
+static void highest_wp_number_add_wp(VikTrwLayer *vtl, const gchar *new_wp_name);
+static void highest_wp_number_remove_wp(VikTrwLayer *vtl, const gchar *old_wp_name);
+
+
static VikToolInterface trw_layer_tools[] = {
- { "Create Waypoint", (VikToolConstructorFunc) tool_new_waypoint_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_new_waypoint_click, NULL, NULL },
+ { N_("Create Waypoint"), (VikToolConstructorFunc) tool_new_waypoint_create, NULL, NULL, NULL,
+ (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, (VikToolMouseMoveFunc) tool_new_track_move, NULL,
+ (VikToolKeyFunc) tool_new_track_key_press, GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf },
- { "Create Track", (VikToolConstructorFunc) tool_new_track_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_new_track_click, NULL, NULL },
+ { N_("Begin Track"), (VikToolConstructorFunc) tool_begin_track_create, NULL, NULL, NULL,
+ (VikToolMouseFunc) tool_begin_track_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf },
- { "Edit Waypoint", (VikToolConstructorFunc) tool_edit_waypoint_create, NULL, NULL, NULL,
+ { 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 },
+ (VikToolMouseMoveFunc) tool_edit_waypoint_move,
+ (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf },
- { "Edit Trackpoint", (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL,
+ { 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 },
+ (VikToolMouseMoveFunc) tool_edit_trackpoint_move,
+ (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf },
- { "Show Picture", (VikToolConstructorFunc) tool_show_picture_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_show_picture_click, NULL, NULL },
+ { N_("Show Picture"), (VikToolConstructorFunc) tool_show_picture_create, NULL, NULL, NULL,
+ (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, 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 };
/****** PARAMETERS ******/
-static gchar *params_groups[] = { "Waypoints", "Tracks", "Waypoint Images" };
+static gchar *params_groups[] = { N_("Waypoints"), N_("Tracks"), N_("Waypoint Images") };
enum { GROUP_WAYPOINTS, GROUP_TRACKS, GROUP_IMAGES };
-static gchar *params_drawmodes[] = { "Draw by Track", "Draw by Velocity", "All Tracks Black", 0 };
-static gchar *params_wpsymbols[] = { "Filled Square", "Square", "Circle", "X", 0 };
+static gchar *params_drawmodes[] = { N_("Draw by Track"), N_("Draw by Velocity"), N_("All Tracks Black"), 0 };
+static gchar *params_wpsymbols[] = { N_("Filled Square"), N_("Square"), N_("Circle"), N_("X"), 0 };
static VikLayerParamScale params_scales[] = {
{ "tracks_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
{ "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
- { "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, "Track Drawing Mode:", VIK_LAYER_WIDGET_RADIOGROUP, params_drawmodes },
- { "drawlines", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, "Draw Track Lines", VIK_LAYER_WIDGET_CHECKBUTTON },
- { "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, "Draw Trackpoints", VIK_LAYER_WIDGET_CHECKBUTTON },
- { "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, "Draw Elevation", VIK_LAYER_WIDGET_CHECKBUTTON },
- { "elevation_factor", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, "Draw Elevation Height %:", VIK_LAYER_WIDGET_HSCALE, params_scales + 9 },
-
- { "drawstops", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, "Draw Stops", VIK_LAYER_WIDGET_CHECKBUTTON },
- { "stop_length", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, "Min Stop Length (seconds):", VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 8 },
-
- { "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, "Track Thickness:", VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 0 },
- { "bg_line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, "Track BG Thickness:", VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 6 },
- { "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, "Track Background Color", VIK_LAYER_WIDGET_COLOR, 0 },
- { "velocity_min", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, "Min Track Velocity:", VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 1 },
- { "velocity_max", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, "Max Track Velocity:", VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 2 },
-
- { "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, "Draw Labels", VIK_LAYER_WIDGET_CHECKBUTTON },
- { "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, "Waypoint Color:", VIK_LAYER_WIDGET_COLOR, 0 },
- { "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, "Waypoint Text:", VIK_LAYER_WIDGET_COLOR, 0 },
- { "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, "Background:", VIK_LAYER_WIDGET_COLOR, 0 },
- { "wpbgand", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, "Fake BG Color Translucency:", VIK_LAYER_WIDGET_CHECKBUTTON, 0 },
- { "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, "Waypoint marker:", VIK_LAYER_WIDGET_RADIOGROUP, params_wpsymbols },
- { "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, "Waypoint size:", VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 7 },
- { "wpsyms", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, "Draw Waypoint Symbols:", VIK_LAYER_WIDGET_CHECKBUTTON },
-
- { "drawimages", VIK_LAYER_PARAM_BOOLEAN, GROUP_IMAGES, "Draw Waypoint Images", VIK_LAYER_WIDGET_CHECKBUTTON },
- { "image_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, "Image Size (pixels):", VIK_LAYER_WIDGET_HSCALE, params_scales + 3 },
- { "image_alpha", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, "Image Alpha:", VIK_LAYER_WIDGET_HSCALE, params_scales + 4 },
- { "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, "Image Memory Cache Size:", VIK_LAYER_WIDGET_HSCALE, params_scales + 5 },
+ { "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Drawing Mode:"), VIK_LAYER_WIDGET_RADIOGROUP, NULL },
+ { "drawlines", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Lines"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Trackpoints"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Elevation"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "elevation_factor", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Draw Elevation Height %:"), VIK_LAYER_WIDGET_HSCALE, params_scales + 9 },
+
+ { "drawstops", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Stops"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "stop_length", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Min Stop Length (seconds):"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 8 },
+
+ { "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 0 },
+ { "bg_line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track BG Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 6 },
+ { "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("Track Background Color"), VIK_LAYER_WIDGET_COLOR, 0 },
+ { "velocity_min", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Min Track Velocity:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 1 },
+ { "velocity_max", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Max Track Velocity:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 2 },
+
+ { "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Color:"), VIK_LAYER_WIDGET_COLOR, 0 },
+ { "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Text:"), VIK_LAYER_WIDGET_COLOR, 0 },
+ { "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Background:"), VIK_LAYER_WIDGET_COLOR, 0 },
+ { "wpbgand", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Fake BG Color Translucency:"), VIK_LAYER_WIDGET_CHECKBUTTON, 0 },
+ { "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint marker:"), VIK_LAYER_WIDGET_RADIOGROUP, NULL },
+ { "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint size:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 7 },
+ { "wpsyms", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Waypoint Symbols:"), VIK_LAYER_WIDGET_CHECKBUTTON },
+
+ { "drawimages", VIK_LAYER_PARAM_BOOLEAN, GROUP_IMAGES, N_("Draw Waypoint Images"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "image_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Size (pixels):"), VIK_LAYER_WIDGET_HSCALE, params_scales + 3 },
+ { "image_alpha", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales + 4 },
+ { "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Memory Cache Size:"), VIK_LAYER_WIDGET_HSCALE, params_scales + 5 },
};
enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PARAM_DS, PARAM_SL, PARAM_LT, PARAM_BLT, PARAM_TBGC, PARAM_VMIN, PARAM_VMAX, PARAM_DLA, PARAM_WPC, PARAM_WPTC, PARAM_WPBC, PARAM_WPBA, PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, PARAM_DI, PARAM_IS, PARAM_IA, PARAM_ICS, NUM_PARAMS };
+/*** TO ADD A PARAM:
+ *** 1) Add to trw_layer_params and enumeration
+ *** 2) Handle in get_param & set_param (presumably adding on to VikTrwLayer struct)
+ ***/
+
/****** END PARAMETERS ******/
VikLayerInterface vik_trw_layer_interface = {
"TrackWaypoint",
- &trwlayer_pixbuf,
+ &viktrwlayer_pixbuf,
trw_layer_tools,
sizeof(trw_layer_tools) / sizeof(VikToolInterface),
(VikLayerFuncSublayerRenameRequest) vik_trw_layer_sublayer_rename_request,
(VikLayerFuncSublayerToggleVisible) vik_trw_layer_sublayer_toggle_visible,
- (VikLayerFuncCopy) trw_layer_copy,
(VikLayerFuncMarshall) trw_layer_marshall,
(VikLayerFuncUnmarshall) trw_layer_unmarshall,
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;
trw_layer_delete_item ( pass_along );
}
+static void trw_layer_copy_item_cb( gpointer pass_along[5])
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+ gint subtype = GPOINTER_TO_INT (pass_along[2]);
+ gpointer * sublayer = pass_along[3];
+ guint8 *data = NULL;
+ guint len;
+
+ trw_layer_copy_item( vtl, subtype, sublayer, &data, &len);
+
+ if (data) {
+ a_clipboard_copy( VIK_CLIPBOARD_DATA_SUBLAYER, VIK_LAYER_TRW,
+ subtype, len, data);
+ }
+}
+
+static void trw_layer_cut_item_cb( gpointer pass_along[5])
+{
+ trw_layer_copy_item_cb(pass_along);
+ trw_layer_delete_item(pass_along);
+}
+
static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len )
{
FlatItem *fi;
}
}
-static void waypoint_copy ( const gchar *name, VikWaypoint *wp, GHashTable *dest )
-{
- g_hash_table_insert ( dest, g_strdup(name), vik_waypoint_copy(wp) );
-}
-
static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp )
{
switch ( id )
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 );
return rv;
}
-static void track_copy ( const gchar *name, VikTrack *tr, GHashTable *dest )
-{
- g_hash_table_insert ( dest, g_strdup ( name ), vik_track_copy(tr) );
-}
-
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;
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));
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;
data += pl;
if (!(f = fdopen(g_file_open_tmp (NULL, &tmpname, NULL), "r+"))) {
- g_critical("couldn't open temp file\n");
+ g_critical("couldn't open temp file");
exit(1);
}
fwrite(data, len - pl - sizeof(pl), 1, f);
rewind(f);
a_gpx_read_file(rv, f);
fclose(f);
- remove(tmpname);
+ f = NULL;
+ g_remove(tmpname);
g_free(tmpname);
return rv;
}
-static VikTrwLayer *trw_layer_copy ( VikTrwLayer *vtl, gpointer vp )
+static GList * str_array_to_glist(gchar* data[])
{
- VikTrwLayer *rv = vik_trw_layer_new ( vtl->drawmode );
- PangoFontDescription *pfd;
- rv->wplabellayout = gtk_widget_create_pango_layout (GTK_WIDGET(vp), NULL);
- pfd = pango_font_description_from_string (WAYPOINT_FONT);
- pango_layout_set_font_description (rv->wplabellayout, pfd);
- /* freeing PangoFontDescription, cause it has been copied by prev. call */
- pango_font_description_free (pfd);
-
- rv->tracks_visible = vtl->tracks_visible;
- rv->waypoints_visible = vtl->waypoints_visible;
- rv->drawpoints = vtl->drawpoints;
- rv->drawstops = vtl->drawstops;
- rv->drawelevation = vtl->drawelevation;
- rv->elevation_factor = vtl->elevation_factor;
- rv->drawlines = vtl->drawlines;
- rv->stop_length = vtl->stop_length;
- rv->line_thickness = vtl->line_thickness;
- rv->bg_line_thickness = vtl->bg_line_thickness;
- rv->velocity_min = vtl->velocity_min;
- rv->velocity_max = vtl->velocity_max;
- rv->drawlabels = vtl->drawlabels;
- rv->drawimages = vtl->drawimages;
- rv->image_size = vtl->image_size;
- rv->image_alpha = vtl->image_alpha;
- rv->image_cache_size = vtl->image_cache_size;
- rv->has_verified_thumbnails = TRUE;
- rv->coord_mode = vtl->coord_mode;
- rv->wp_symbol = vtl->wp_symbol;
- rv->wp_size = vtl->wp_size;
- rv->wp_draw_symbols = vtl->wp_draw_symbols;
-
- trw_layer_new_track_gcs ( rv, VIK_VIEWPORT(vp) );
-
- rv->waypoint_gc = gdk_gc_new ( GTK_WIDGET(vp)->window );
- gdk_gc_set_line_attributes ( rv->waypoint_gc, 2, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND );
-
- rv->waypoint_text_gc = gdk_gc_new ( GTK_WIDGET(vp)->window );
- rv->waypoint_bg_gc = gdk_gc_new ( GTK_WIDGET(vp)->window );
- gdk_gc_copy ( rv->waypoint_gc, vtl->waypoint_gc );
- gdk_gc_copy ( rv->waypoint_text_gc, vtl->waypoint_text_gc );
- gdk_gc_copy ( rv->waypoint_bg_gc, vtl->waypoint_bg_gc );
+ GList *gl = NULL;
+ gpointer * p;
+ for (p = (gpointer)data; *p; p++)
+ gl = g_list_prepend(gl, *p);
+ return(g_list_reverse(gl));
+}
- rv->waypoint_font = gdk_font_load ( "-*-helvetica-bold-r-normal-*-*-100-*-*-p-*-iso8859-1" );
+static gboolean strcase_equal(gconstpointer s1, gconstpointer s2)
+{
+ return (strcasecmp(s1, s2) == 0);
+}
- g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_copy, rv->waypoints );
- g_hash_table_foreach ( vtl->tracks, (GHFunc) track_copy, rv->tracks );
+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 rv;
+ 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 = str_array_to_glist(params_drawmodes);
+ if (trw_layer_params[PARAM_WPSYM].widget_data == NULL)
+ 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;
rv->current_tp_track_name = NULL;
rv->moving_tp = FALSE;
rv->moving_wp = FALSE;
+
+ rv->ct_sync_done = TRUE;
+
+ rv->magic_scissors_started = FALSE;
+ rv->magic_scissors_check_added_track = FALSE;
+ rv->magic_scissors_added_track_name = NULL;
+ rv->magic_scissors_current_track = NULL;
+ rv->magic_scissors_append = FALSE;
+
rv->waypoint_rightclick = FALSE;
rv->last_tpl = NULL;
rv->last_tp_track_name = NULL;
{
/* TODO: this function is a mess, get rid of any redundancy */
GList *list = track->trackpoints;
+ GdkGC *main_gc;
gboolean useoldvals = TRUE;
gboolean drawpoints;
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
+ main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+
if (list) {
int x, y, oldx, oldy;
VikTrackpoint *tp = VIK_TRACKPOINT(list->data);
if ( (drawpoints) && dp->track_gc_iter < VIK_TRW_LAYER_TRACK_GC )
{
GdkPoint trian[3] = { { x, y-(3*tp_size) }, { x-(2*tp_size), y+(2*tp_size) }, {x+(2*tp_size), y+(2*tp_size)} };
- vik_viewport_draw_polygon ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), TRUE, trian, 3 );
+ vik_viewport_draw_polygon ( dp->vp, main_gc, TRUE, trian, 3 );
}
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);
if ( drawpoints && ! drawing_white_background )
{
if ( list->next ) {
- vik_viewport_draw_rectangle ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
+ vik_viewport_draw_rectangle ( dp->vp, main_gc, TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
- vik_viewport_draw_rectangle ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
+ vik_viewport_draw_rectangle ( dp->vp, main_gc, TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
/* stops */
if ( drawstops && VIK_TRACKPOINT(list->next->data)->timestamp - VIK_TRACKPOINT(list->data)->timestamp > dp->vtl->stop_length )
vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, 11), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
}
else
- vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), TRUE, x-(2*tp_size), y-(2*tp_size), 4*tp_size, 4*tp_size, 0, 360*64 );
+ vik_viewport_draw_arc ( dp->vp, main_gc, TRUE, x-(2*tp_size), y-(2*tp_size), 4*tp_size, 4*tp_size, 0, 360*64 );
}
if ((!tp->newsegment) && (dp->vtl->drawlines))
/* UTM only: zone check */
if ( drawpoints && dp->vtl->coord_mode == VIK_COORD_UTM && tp->coord.utm_zone != dp->center->utm_zone )
- draw_utm_skip_insignia ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), x, y);
+ draw_utm_skip_insignia ( dp->vp, main_gc, x, y);
if ( dp->vtl->drawmode == DRAWMODE_BY_VELOCITY )
dp->track_gc_iter = calculate_velocity ( dp->vtl, tp, tp2 );
}
else {
- vik_viewport_draw_line ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), oldx, oldy, x, y);
+ vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
if ( dp->vtl->drawelevation && list && list->next && VIK_TRACKPOINT(list->next->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
GdkPoint tmp[4];
#define FIXALTITUDE(what) ((VIK_TRACKPOINT((what))->altitude-min_alt)/alt_diff*DRAW_ELEVATION_FACTOR*dp->vtl->elevation_factor/dp->xmpp)
tmp_gc = GTK_WIDGET(dp->vp)->style->dark_gc[0];
vik_viewport_draw_polygon ( dp->vp, tmp_gc, TRUE, tmp, 4);
}
- vik_viewport_draw_line ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), oldx, oldy-FIXALTITUDE(list->data), x, y-FIXALTITUDE(list->next->data));
+ vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy-FIXALTITUDE(list->data), x, y-FIXALTITUDE(list->next->data));
}
}
}
if ( drawing_white_background )
vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
else
- vik_viewport_draw_line ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), oldx, oldy, x, y);
+ vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
}
else
{
vik_viewport_coord_to_screen ( dp->vp, &(tp2->coord), &x, &y );
- draw_utm_skip_insignia ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter), x, y );
+ draw_utm_skip_insignia ( dp->vp, main_gc, x, y );
}
}
useoldvals = FALSE;
static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct DrawingParams *dp )
{
if ( wp->visible )
- if ( (!dp->one_zone) || ( wp->coord.utm_zone == dp->center->utm_zone &&
+ if ( (!dp->one_zone && !dp->lat_lon) || ( ( dp->lat_lon || wp->coord.utm_zone == dp->center->utm_zone ) &&
wp->coord.east_west < dp->ce2 && wp->coord.east_west > dp->ce1 &&
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 */
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 );
}
}
}
g_object_unref ( vtl->track_bg_gc );
vtl->track_bg_gc = NULL;
}
+ if ( vtl->current_track_gc )
+ {
+ g_object_unref ( vtl->current_track_gc );
+ vtl->current_track_gc = NULL;
+ }
if ( ! vtl->track_gc )
return;
g_object_unref ( vtl->track_bg_gc );
vtl->track_bg_gc = vik_viewport_new_gc ( vp, "#FFFFFF", width + vtl->bg_line_thickness );
+ if ( vtl->current_track_gc )
+ g_object_unref ( vtl->current_track_gc );
+ vtl->current_track_gc = vik_viewport_new_gc ( vp, "#FF0000", 2 );
+ gdk_gc_set_line_attributes ( vtl->current_track_gc, 2, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
+
vtl->track_gc = g_array_sized_new ( FALSE, FALSE, sizeof ( GdkGC * ), VIK_TRW_LAYER_TRACK_GC );
gc[0] = vik_viewport_new_gc ( vp, "#2d870a", width ); /* below range */
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
{
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
gpointer pass_along[5] = { &(vtl->tracks_iter), &iter2, vtl, vt, (gpointer) VIK_TRW_LAYER_SUBLAYER_TRACK };
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
- vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->tracks_iter), "Tracks", vtl, NULL, VIK_TRW_LAYER_SUBLAYER_TRACKS, NULL, TRUE, FALSE );
+ vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->tracks_iter), _("Tracks"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_TRACKS, NULL, TRUE, FALSE );
#else
- vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->tracks_iter), "Tracks", vtl, NULL, VIK_TRW_LAYER_SUBLAYER_TRACKS, NULL, TRUE, FALSE );
+ vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->tracks_iter), _("Tracks"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_TRACKS, NULL, TRUE, FALSE );
#endif
if ( ! vtl->tracks_visible )
vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->tracks_iter), FALSE );
g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_realize_track, pass_along );
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
- vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->waypoints_iter), "Waypoints", vtl, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINTS, NULL, TRUE, FALSE );
+ vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->waypoints_iter), _("Waypoints"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINTS, NULL, TRUE, FALSE );
#else
- vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->waypoints_iter), "Waypoints", vtl, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINTS, NULL, TRUE, FALSE );
+ vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->waypoints_iter), _("Waypoints"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINTS, NULL, TRUE, FALSE );
#endif
if ( ! vtl->waypoints_visible )
}
}
+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
if ( vik_trw_layer_find_center ( VIK_TRW_LAYER(layer_and_vlp[0]), &coord ) )
goto_coord ( VIK_LAYERS_PANEL(layer_and_vlp[1]), &coord );
else
- a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), "This layer has no waypoints or trackpoints." );
+ a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("This layer has no waypoints or trackpoints.") );
}
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");
-
- 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 );
}
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 );
}
gtk_widget_destroy ( file_selector );
if ( failed )
- a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), "The filename you requested could not be opened for writing." );
+ a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("The filename you requested could not be opened for writing.") );
}
static void trw_layer_export_gpspoint ( 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,
NULL);
GtkWidget *label, *entry;
- label = gtk_label_new("Waypoint Name:");
+ label = gtk_label_new(_("Waypoint Name:"));
entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), label, FALSE, FALSE, 0);
wp = g_hash_table_lookup ( wps, upname );
if (!wp)
- a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), "Waypoint not found in this layer." );
+ a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("Waypoint not found in this layer.") );
else
{
vik_viewport_set_center_coord ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(layer_and_vlp[1])), &(wp->coord) );
gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikCoord *def_coord )
{
- gchar *name;
+ 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 ) )
{
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]);
{
static gpointer pass_along[2];
GtkWidget *item;
+ GtkWidget *export_submenu;
+ GtkWidget *wikipedia_submenu;
pass_along[0] = vtl;
pass_along[1] = vlp;
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Goto Center of Layer" );
+ item = gtk_menu_item_new_with_label ( _("Goto Center of Layer") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_centerize), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Goto Waypoint" );
+ item = gtk_menu_item_new_with_label ( _("Goto Waypoint") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_wp), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Export Layer as GPSPoint" );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpspoint), pass_along );
+ export_submenu = gtk_menu_new ();
+ item = gtk_menu_item_new_with_label ( _("Export layer") );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), export_submenu );
+
+ item = gtk_menu_item_new_with_label ( _("Export as GPSPoint") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpspoint), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
+ gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Export Layer as GPSMapper" );
+ item = gtk_menu_item_new_with_label ( _("Export as GPSMapper") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpsmapper), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Export Layer as GPX" );
+ item = gtk_menu_item_new_with_label ( _("Export as GPX") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpx), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "New Waypoint" );
+ item = gtk_menu_item_new_with_label ( _("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 );
+
+#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 );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+#endif
+
+ item = a_acquire_trwlayer_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vlp,
+ vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)), vtl );
+ if ( item ) {
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ }
+
+ item = a_acquire_trwlayer_track_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vlp,
+ vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)), vtl );
+ if ( item ) {
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ }
}
void vik_trw_layer_add_waypoint ( VikTrwLayer *vtl, gchar *name, VikWaypoint *wp )
else
wp->visible = TRUE;
+ highest_wp_number_add_wp(vtl, name);
g_hash_table_insert ( vtl->waypoints, name, wp );
}
{
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 );
}
-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. */
-static void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, const gchar *trk_name )
+void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, const gchar *trk_name )
{
if (vtl->current_tp_track_name && g_strcasecmp(trk_name, vtl->current_tp_track_name) == 0)
trw_layer_cancel_current_tp ( vtl, FALSE );
}
void vik_trw_layer_filein_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *tr )
{
- vik_trw_layer_add_track ( vtl,
- get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, name),
- tr );
+ if ( vtl->magic_scissors_append && vtl->magic_scissors_current_track ) {
+ vik_track_remove_dup_points ( tr ); /* make "double point" track work to undo */
+ vik_track_steal_and_append_trackpoints ( vtl->magic_scissors_current_track, tr );
+ vik_track_free ( tr );
+ vtl->magic_scissors_append = FALSE; /* this means we have added it */
+ } else {
+ gchar *new_name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, name);
+ vik_trw_layer_add_track ( vtl, new_name, tr );
+
+ if ( vtl->magic_scissors_check_added_track ) {
+ vik_track_remove_dup_points ( tr ); /* make "double point" track work to undo */
+ if ( vtl->magic_scissors_added_track_name ) /* for google routes */
+ g_free ( vtl->magic_scissors_added_track_name );
+ vtl->magic_scissors_added_track_name = g_strdup(new_name);
+ }
+ }
}
static void trw_layer_enum_item ( const gchar *name, GList **tr, GList **l )
was_visible = t->visible;
if ( t == vtl->current_track )
vtl->current_track = NULL;
+ if ( t == vtl->magic_scissors_current_track )
+ vtl->magic_scissors_current_track = NULL;
/* could be current_tp, so we have to check */
trw_layer_cancel_tps_of_track ( vtl, trk_name );
g_assert ( ( it = g_hash_table_lookup ( vtl->waypoints_iters, (gchar *) wp_name ) ) );
vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
g_hash_table_remove ( vtl->waypoints_iters, (gchar *) wp_name );
+
+ highest_wp_number_remove_wp(vtl, wp_name);
g_hash_table_remove ( vtl->waypoints, wp_name ); /* last because this frees name */
}
return was_visible;
}
+static void remove_item_from_treeview(const gchar *name, GtkTreeIter *it, VikTreeview * vt)
+{
+ vik_treeview_item_delete (vt, it );
+}
+
+void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
+{
+
+ vtl->current_track = NULL;
+ vtl->magic_scissors_current_track = NULL;
+ if (vtl->current_tp_track_name)
+ trw_layer_cancel_current_tp(vtl, FALSE);
+ if (vtl->last_tp_track_name)
+ trw_layer_cancel_last_tp ( vtl );
+
+ g_hash_table_foreach(vtl->tracks_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
+ g_hash_table_remove_all(vtl->tracks_iters);
+ g_hash_table_remove_all(vtl->tracks);
+
+ /* TODO: only update if the layer is visible (ticked) */
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
+void vik_trw_layer_delete_all_waypoints ( VikTrwLayer *vtl )
+{
+ vtl->current_wp = NULL;
+ vtl->current_wp_name = NULL;
+ vtl->moving_wp = FALSE;
+
+ highest_wp_number_reset(vtl);
+
+ g_hash_table_foreach(vtl->waypoints_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
+ g_hash_table_remove_all(vtl->waypoints_iters);
+ g_hash_table_remove_all(vtl->waypoints);
+
+ /* TODO: only update if the layer is visible (ticked) */
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
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] );
}
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 )
VikTrack *tr = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
if ( tr )
{
- gint resp = vik_trw_layer_propwin_run ( VIK_GTK_WINDOW_FROM_LAYER(vtl), tr, pass_along[1] /* vlp */ );
- if ( resp == VIK_TRW_LAYER_PROPWIN_DEL_DUP )
- {
- vik_track_remove_dup_points(tr);
- /* above operation could have deleted current_tp or last_tp */
- trw_layer_cancel_tps_of_track ( vtl, (gchar *) pass_along[3] );
- vik_layer_emit_update ( VIK_LAYER(vtl) );
- }
- if ( resp == VIK_TRW_LAYER_PROPWIN_REVERSE )
- {
- vik_track_reverse(tr);
- vik_layer_emit_update ( VIK_LAYER(vtl) );
- }
- else if ( resp == VIK_TRW_LAYER_PROPWIN_SPLIT )
- {
- /* get new tracks, add them, resolve naming conflicts (free if cancel), and delete old. old can still exist on clipboard. */
- guint ntracks;
- VikTrack **tracks = vik_track_split_into_segments(tr, &ntracks);
- gchar *new_tr_name;
- guint i;
- for ( i = 0; i < ntracks; i++ )
- {
- g_assert ( tracks[i] );
- new_tr_name = g_strdup_printf("%s #%d", (gchar *) pass_along[3], i+1);
- /* if ( (wp_exists) && (! overwrite) ) */
- /* don't need to upper case new_tr_name because old tr name was uppercase */
- if ( g_hash_table_lookup ( vtl->tracks, new_tr_name ) &&
- ( ! a_dialog_overwrite ( VIK_GTK_WINDOW_FROM_LAYER(vtl), "The track \"%s\" exists, do you wish to overwrite it?", new_tr_name ) ) )
- {
- gchar *new_new_tr_name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks );
- g_free ( new_tr_name );
- if (new_new_tr_name)
- new_tr_name = new_new_tr_name;
- else
- {
- new_tr_name = NULL;
- vik_track_free ( tracks[i] );
- }
- }
- if ( new_tr_name )
- vik_trw_layer_add_track ( vtl, new_tr_name, tracks[i] );
- }
- if ( tracks )
- {
- g_free ( tracks );
- vik_trw_layer_delete_track ( vtl, (gchar *) pass_along[3] );
- vik_layer_emit_update ( VIK_LAYER(vtl) ); /* chase thru the hoops */
- }
- }
+ vik_trw_layer_propwin_run ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ vtl, tr,
+ pass_along[1], /* vlp */
+ pass_along[3] /* track name */);
}
}
}
static void trw_layer_goto_track_center ( gpointer pass_along[5] )
{
+ /* FIXME: get this into viktrack.c, and should be ->trackpoints right? */
GList **trps = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
if ( trps && *trps )
{
}
}
+static void trw_layer_extend_track_end ( 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] );
+
+ vtl->current_track = 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. */
+ /* Also warn if overwrite old elevation data */
+ VikTrack *track = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+
+ vik_track_apply_dem_data ( track );
+}
+
static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] )
{
GList *trps = ((VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ))->trackpoints;
* 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]
*/
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]);
- t1 = VIK_TRACKPOINT(orig_track->data)->timestamp;
- t2 = VIK_TRACKPOINT(g_list_last(orig_track)->data)->timestamp;
+ /* outline:
+ * detect reasons for not merging, and return
+ * if no reason is found not to merge, then do it.
+ */
if (VIK_TRACK(value)->trackpoints == orig_track) {
return;
}
- p1 = VIK_TRACKPOINT(VIK_TRACK(value)->trackpoints->data);
- p2 = VIK_TRACKPOINT(g_list_last(VIK_TRACK(value)->trackpoints)->data);
+ t1 = VIK_TRACKPOINT(orig_track->data)->timestamp;
+ t2 = VIK_TRACKPOINT(g_list_last(orig_track)->data)->timestamp;
- if (!p1->has_timestamp || !p2->has_timestamp) {
- g_print("no timestamp\n");
- 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);
- /* g_print("Got track named %s, times %d, %d\n", (gchar *)key, p1->timestamp, p2->timestamp); */
- if (abs(t1 - p2->timestamp) < thr*60 ||
- /* p1 p2 t1 t2 */
- abs(p1->timestamp - t2) < thr*60
- /* t1 t2 p1 p2 */
- ) {
- *nearby_tracks = g_list_prepend(*nearby_tracks, key);
+ if (!p1->has_timestamp || !p2->has_timestamp) {
+ g_print("no timestamp\n");
+ return;
+ }
+
+ /* g_print("Got track named %s, times %d, %d\n", (gchar *)key, p1->timestamp, p2->timestamp); */
+ if (! (abs(t1 - p2->timestamp) < thr*60 ||
+ /* p1 p2 t1 t2 */
+ abs(p1->timestamp - t2) < thr*60)
+ /* t1 t2 p1 p2 */
+ ) {
+ return;
+ }
}
+
+ *nearby_tracks = g_list_prepend(*nearby_tracks, key);
}
/* comparison function used to sort tracks; a and b are hash table keys */
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] )
{
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ gchar *orig_track_name = strdup(pass_along[3]);
+
time_t t1, t2;
- GList *nearby_tracks = NULL;
+ GList *nearby_tracks;
VikTrack *track;
GList *trps;
static guint thr = 1;
guint track_count = 0;
- gchar *orig_track_name = strdup(pass_along[3]);
- if (!a_dialog_time_threshold(VIK_GTK_WINDOW_FROM_LAYER(pass_along[0]),
- "Merge Threshold...",
- "Merge when time between trackpoints less than:",
+ if (!a_dialog_time_threshold(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Merge Threshold..."),
+ _("Merge when time between tracks less than:"),
&thr)) {
+ free(orig_track_name);
return;
}
/* merge tracks until we can't */
+ nearby_tracks = NULL;
do {
gpointer params[3];
- track = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, orig_track_name );
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name );
trps = track->trackpoints;
if ( !trps )
return;
/* 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(VIK_TRW_LAYER(pass_along[0])->tracks, find_nearby_track, (gpointer)params);
+ g_hash_table_foreach(vtl->tracks, find_nearby_track, (gpointer)params);
/* add original track */
nearby_tracks = g_list_prepend(nearby_tracks, orig_track_name);
- /* sort by first trackpoint; assumes they don't overlap */
- nearby_tracks = g_list_sort_with_data(nearby_tracks, track_compare, VIK_TRW_LAYER(pass_along[0])->tracks);
-
/* merge them */
{
-#define get_track(x) VIK_TRACK(g_hash_table_lookup(VIK_TRW_LAYER(pass_along[0])->tracks, (gchar *)((x)->data)))
+#define get_track(x) VIK_TRACK(g_hash_table_lookup(vtl->tracks, (gchar *)((x)->data)))
#define get_first_trackpoint(x) VIK_TRACKPOINT(get_track(x)->trackpoints->data)
#define get_last_trackpoint(x) VIK_TRACKPOINT(g_list_last(get_track(x)->trackpoints)->data)
GList *l = nearby_tracks;
/* remove trackpoints from merged track, delete track */
tr->trackpoints = g_list_concat(tr->trackpoints, get_track(l)->trackpoints);
get_track(l)->trackpoints = NULL;
- vik_trw_layer_delete_track(VIK_TRW_LAYER(pass_along[0]), l->data);
+ vik_trw_layer_delete_track(vtl, l->data);
track_count ++;
l = g_list_next(l);
}
tr->trackpoints = g_list_sort(tr->trackpoints, trackpoint_compare);
- vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), strdup(orig_track_name), tr);
+ vik_trw_layer_add_track(vtl, strdup(orig_track_name), tr);
#undef get_first_trackpoint
#undef get_last_trackpoint
} while (track_count > 1);
g_list_free(nearby_tracks);
free(orig_track_name);
- vik_layer_emit_update(VIK_LAYER(pass_along[0]));
+ vik_layer_emit_update( VIK_LAYER(vtl) );
}
/* split by time routine */
return;
if (!a_dialog_time_threshold(VIK_GTK_WINDOW_FROM_LAYER(pass_along[0]),
- "Split Threshold...",
- "Split when time between trackpoints exceeds:",
+ _("Split Threshold..."),
+ _("Split when time between trackpoints exceeds:"),
&thr)) {
return;
}
static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[5] )
{
gchar *webpage = g_strdup_printf("http://www.geocaching.com/seek/cache_details.aspx?wp=%s", (gchar *) pass_along[3] );
-#ifdef WINDOWS
- ShellExecute(NULL, NULL, (char *) webpage, NULL, ".\\", 0);
-#else /* WINDOWS */
- GError *err = NULL;
- gchar *cmd = g_strdup_printf ( "%s %s", UNIX_WEB_BROWSER, webpage );
- if ( ! g_spawn_command_line_async ( cmd, &err ) )
- {
- a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(pass_along[0])), "Could not launch web browser." );
- g_error_free ( err );
- }
- g_free ( cmd );
-#endif /* WINDOWS */
+ open_url(VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(pass_along[0])), webpage);
g_free ( webpage );
}
{
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 );
g_hash_table_steal ( l->waypoints_iters, sublayer );
wp = vik_waypoint_copy ( VIK_WAYPOINT(g_hash_table_lookup ( l->waypoints, sublayer )) );
+ highest_wp_number_remove_wp(l, sublayer);
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 );
+ highest_wp_number_add_wp(l, rv);
g_hash_table_insert ( l->waypoints, rv, wp );
g_hash_table_insert ( l->waypoints_iters, rv, iter );
}
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 );
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 );
static gboolean is_valid_geocache_name ( gchar *str )
{
gint len = strlen ( str );
- return len >= 3 && len <= 6 && str[0] == 'G' && str[1] == 'C' && isalnum(str[2]) && (len < 4 || isalnum(str[3])) && (len < 5 || isalnum(str[4])) && (len < 6 || isalnum(str[5]));
+ return len >= 3 && len <= 7 && str[0] == 'G' && str[1] == 'C' && isalnum(str[2]) && (len < 4 || isalnum(str[3])) && (len < 5 || isalnum(str[4])) && (len < 6 || isalnum(str[5])) && (len < 7 || isalnum(str[6]));
+}
+
+static void trw_layer_track_use_with_filter ( gpointer *pass_along )
+{
+ gchar *track_name = (gchar *) pass_along[3];
+ VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, track_name );
+ a_acquire_set_filter_track ( tr, track_name );
+}
+
+static gboolean is_valid_google_route ( VikTrwLayer *vtl, const gchar *track_name )
+{
+ VikTrack *tr = g_hash_table_lookup ( vtl->tracks, track_name );
+ return ( tr && tr->comment && strlen(tr->comment) > 7 && !strncmp(tr->comment, "from:", 5) );
+}
+
+static void trw_layer_track_google_route_webpage( gpointer *pass_along )
+{
+ gchar *track_name = (gchar *) pass_along[3];
+ VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, track_name );
+ if ( tr ) {
+ gchar *escaped = uri_escape ( tr->comment );
+ gchar *webpage = g_strdup_printf("http://maps.google.com/maps?f=q&hl=en&q=%s", escaped );
+ open_url(VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(pass_along[0])), webpage);
+ g_free ( escaped );
+ g_free ( webpage );
+ }
}
/* vlp can be NULL if necessary - i.e. right-click from a tool -- but be careful, some functions may try to use it */
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;
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
+ if (subtype == VIK_TRW_LAYER_SUBLAYER_TRACK) {
+ VikTrwLayer *vtl = l;
+ VikTrack *tr = g_hash_table_lookup ( vtl->tracks, sublayer );
+ if (tr && tr->property_dialog)
+ gtk_widget_set_sensitive(GTK_WIDGET(item), FALSE );
+ }
+
+ item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_CUT, NULL );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_cut_item_cb), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_COPY, NULL );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_copy_item_cb), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_DELETE, NULL );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_item), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
{
/* could be a right-click using the tool */
if ( vlp != NULL ) {
- item = gtk_menu_item_new_with_label ( "Goto" );
+ item = gtk_menu_item_new_with_label ( _("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 );
gtk_widget_show ( item );
if ( is_valid_geocache_name ( (gchar *) sublayer ) )
{
- item = gtk_menu_item_new_with_label ( "Visit Geocache Webpage" );
+ item = gtk_menu_item_new_with_label ( _("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 );
gtk_widget_show ( item );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Goto Startpoint" );
+ item = gtk_menu_item_new_with_label ( _("Goto Startpoint") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_startpoint), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Goto \"Center\"" );
+ item = gtk_menu_item_new_with_label ( _("Goto \"Center\"") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_center), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Goto Endpoint" );
+ item = gtk_menu_item_new_with_label ( _("Goto Endpoint") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_endpoint), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "Merge By Time" );
+ item = gtk_menu_item_new_with_label ( _("Merge By Time") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_timestamp), 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" );
+ 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 );
gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_label ( _("Download 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 );
+ gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_label ( _("Apply DEM Data") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_apply_dem_data), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
+ 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 );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+#endif
+
+ if ( is_valid_google_route ( l, (gchar *) sublayer ) )
+ {
+ 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") );
+ 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 );
+
+ item = a_acquire_track_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(l)), vlp,
+ vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)),
+ g_hash_table_lookup ( l->tracks, (gchar *) sublayer ) );
+ if ( item ) {
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ }
}
if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( "New Waypoint" );
+ item = gtk_menu_item_new_with_label ( _("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 );
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 ();
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));
}
vik_viewport_draw_rectangle ( vvp, t->gc, FALSE, x-3, y-3, 6, 6 );
t->oldx = x;
t->oldy = y;
+
if (tool_sync_done) {
g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, tool_sync, vvp, NULL);
tool_sync_done = FALSE;
gint x, y;
vik_viewport_coord_to_screen ( vvp, &(vtl->current_wp->coord), &x, &y );
- if ( abs(x - event->x) < WAYPOINT_SIZE_APPROX &&
- abs(y - event->y) < WAYPOINT_SIZE_APPROX )
+ if ( abs(x - event->x) <= WAYPOINT_SIZE_APPROX &&
+ abs(y - event->y) <= WAYPOINT_SIZE_APPROX )
{
if ( event->button == 3 )
vtl->waypoint_rightclick = TRUE; /* remember that we're clicking; other layers will ignore release signal */
{
/* how do we get here? I'm putting in the abort until we can figure it out. -alex */
marker_begin_move(t, event->x, event->y);
- printf("Abort: shouldn't be here\n");
+ g_critical("shouldn't be here");
exit(1);
}
else if ( params.closest_wp )
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;
{
gint x, y;
vik_viewport_coord_to_screen ( vvp, &new_coord, &x, &y );
+
marker_moveto ( t, x, y );
}
return TRUE;
return FALSE;
}
+/**** Begin track ***/
+static gpointer tool_begin_track_create ( VikWindow *vw, VikViewport *vvp)
+{
+ return vvp;
+}
+
+static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+ vtl->current_track = NULL;
+ return tool_new_track_click ( vtl, event, vvp );
+}
+
/*** New track ****/
static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp)
return vvp;
}
+typedef struct {
+ VikTrwLayer *vtl;
+ VikViewport *vvp;
+ gint x1,y1,x2,y2;
+} new_track_move_passalong_t;
+
+/* sync and undraw, but only when we have time */
+static gboolean ct_sync ( gpointer passalong )
+{
+ new_track_move_passalong_t *p = (new_track_move_passalong_t *) passalong;
+ vik_viewport_sync ( p->vvp );
+ gdk_gc_set_function ( p->vtl->current_track_gc, GDK_INVERT );
+ vik_viewport_draw_line ( p->vvp, p->vtl->current_track_gc, p->x1, p->y1, p->x2, p->y2 );
+ gdk_gc_set_function ( p->vtl->current_track_gc, GDK_COPY );
+ p->vtl->ct_sync_done = TRUE;
+ g_free ( p );
+ return FALSE;
+}
+
+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 ) {
+ GList *iter = vtl->current_track->trackpoints;
+ new_track_move_passalong_t *passalong;
+ gint x1, y1;
+
+ while ( iter->next )
+ iter = iter->next;
+ gdk_gc_set_function ( vtl->current_track_gc, GDK_INVERT );
+ vik_viewport_coord_to_screen ( vvp, &(VIK_TRACKPOINT(iter->data)->coord), &x1, &y1 );
+ vik_viewport_draw_line ( vvp, vtl->current_track_gc, x1, y1, event->x, event->y );
+ gdk_gc_set_function ( vtl->current_track_gc, GDK_COPY );
+
+ passalong = g_new(new_track_move_passalong_t,1); /* freed by sync */
+ passalong->vtl = vtl;
+ passalong->vvp = vvp;
+ passalong->x1 = x1;
+ passalong->y1 = y1;
+ passalong->x2 = event->x;
+ passalong->y2 = event->y;
+
+ /* this will sync and undraw when we have time to */
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, ct_sync, passalong, NULL);
+ vtl->ct_sync_done = FALSE;
+ return VIK_LAYER_TOOL_ACK_GRAB_FOCUS;
+ }
+ return VIK_LAYER_TOOL_ACK;
+}
+
+static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp )
+{
+ if ( vtl->current_track && event->keyval == GDK_Escape ) {
+ vtl->current_track = NULL;
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ return TRUE;
+ } else if ( vtl->current_track && event->keyval == GDK_BackSpace ) {
+ /* undo */
+ if ( vtl->current_track->trackpoints )
+ {
+ GList *last = g_list_last(vtl->current_track->trackpoints);
+ g_free ( last->data );
+ vtl->current_track->trackpoints = g_list_remove_link ( vtl->current_track->trackpoints, last );
+ }
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ return TRUE;
+ }
+ return FALSE;
+}
+
static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
{
VikTrackpoint *tp;
/* undo last, then end */
vtl->current_track = NULL;
}
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
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;
vik_trw_layer_add_track ( vtl, name, vtl->current_track );
+
+ /* incase it was created by begin track */
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK );
}
else
return TRUE;
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;
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;
if ( t->holding )
{
VikCoord new_coord;
- GdkGC *gc;
vik_viewport_screen_to_coord ( vvp, event->x, event->y, &new_coord );
/* snap to TP */
}
+/*** Magic Scissors ***/
+static gpointer tool_magic_scissors_create ( VikWindow *vw, VikViewport *vvp)
+{
+ return vvp;
+}
+
+static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+ VikCoord tmp;
+ if ( !vtl ) return FALSE;
+ vik_viewport_screen_to_coord ( vvp, event->x, event->y, &tmp );
+ if ( event->button == 3 && vtl->magic_scissors_current_track ) {
+ VikCoord *new_end;
+ new_end = vik_track_cut_back_to_double_point ( vtl->magic_scissors_current_track );
+ if ( new_end ) {
+ vtl->magic_scissors_coord = *new_end;
+ g_free ( new_end );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ /* remove last ' to:...' */
+ if ( vtl->magic_scissors_current_track->comment ) {
+ gchar *last_to = strrchr ( vtl->magic_scissors_current_track->comment, 't' );
+ if ( last_to && (last_to - vtl->magic_scissors_current_track->comment > 1) ) {
+ gchar *new_comment = g_strndup ( vtl->magic_scissors_current_track->comment,
+ last_to - vtl->magic_scissors_current_track->comment - 1);
+ vik_track_set_comment_no_copy ( vtl->magic_scissors_current_track, new_comment );
+ }
+ }
+ }
+ }
+ else if ( vtl->magic_scissors_started || (event->state & GDK_CONTROL_MASK && vtl->magic_scissors_current_track) ) {
+ struct LatLon start, end;
+ 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 );
+ vtl->magic_scissors_coord = tmp; /* for continuations */
+
+ /* these are checked when adding a track from a file (vik_trw_layer_filein_add_track) */
+ if ( event->state & GDK_CONTROL_MASK && vtl->magic_scissors_current_track ) {
+ vtl->magic_scissors_append = TRUE; // merge tracks. keep started true.
+ } else {
+ vtl->magic_scissors_check_added_track = TRUE;
+ vtl->magic_scissors_started = FALSE;
+ }
+
+ 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 ) {
+ VikTrack *tr;
+
+ 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 ) );
+
+ vtl->magic_scissors_current_track = tr;
+
+ g_free ( vtl->magic_scissors_added_track_name );
+ vtl->magic_scissors_added_track_name = NULL;
+ } else if ( vtl->magic_scissors_append == FALSE && vtl->magic_scissors_current_track ) {
+ /* magic_scissors_append was originally TRUE but set to FALSE by filein_add_track */
+ gchar *new_comment = g_strdup_printf("%s to: %f,%f", vtl->magic_scissors_current_track->comment, end.lat, end.lon );
+ vik_track_set_comment_no_copy ( vtl->magic_scissors_current_track, new_comment );
+ }
+ vtl->magic_scissors_check_added_track = FALSE;
+ vtl->magic_scissors_append = FALSE;
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ } else {
+ vtl->magic_scissors_started = TRUE;
+ vtl->magic_scissors_coord = tmp;
+ vtl->magic_scissors_current_track = NULL;
+ }
+ return TRUE;
+}
+
/*** Show picture ****/
static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp)
g_free ( quoted_file );
if ( ! g_spawn_command_line_async ( cmd, &err ) )
{
- a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), "Could not launch eog to open file." );
+ a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Could not launch eog to open file.") );
g_error_free ( err );
}
g_free ( cmd );
if ( pics )
{
gint len = g_slist_length ( pics );
- gchar *tmp = g_strdup_printf ( "Creating %d Image Thumbnails...", len );
+ 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 );
g_free ( tmp );
}
return g_hash_table_lookup ( vtl->tracks, name );
}
-static vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16 selection)
+static void vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16 selection)
{
vtl->menu_selection = selection;
}
return(vtl->menu_selection);
}
+/* ----------- Downloading maps along tracks --------------- */
+
+static int get_download_area_width(VikViewport *vvp, gdouble zoom_level, struct LatLon *wh)
+{
+ /* TODO: calculating based on current size of viewport */
+ const gdouble w_at_zoom_0_125 = 0.0013;
+ const gdouble h_at_zoom_0_125 = 0.0011;
+ gdouble zoom_factor = zoom_level/0.125;
+
+ wh->lat = h_at_zoom_0_125 * zoom_factor;
+ wh->lon = w_at_zoom_0_125 * zoom_factor;
+
+ return 0; /* all OK */
+}
+
+static VikCoord *get_next_coord(VikCoord *from, VikCoord *to, struct LatLon *dist, gdouble gradient)
+{
+ if ((dist->lon >= ABS(to->east_west - from->east_west)) &&
+ (dist->lat >= ABS(to->north_south - from->north_south)))
+ return NULL;
+
+ VikCoord *coord = g_malloc(sizeof(VikCoord));
+ coord->mode = VIK_COORD_LATLON;
+
+ if (ABS(gradient) < 1) {
+ if (from->east_west > to->east_west)
+ coord->east_west = from->east_west - dist->lon;
+ else
+ coord->east_west = from->east_west + dist->lon;
+ coord->north_south = gradient * (coord->east_west - from->east_west) + from->north_south;
+ } else {
+ if (from->north_south > to->north_south)
+ coord->north_south = from->north_south - dist->lat;
+ else
+ coord->north_south = from->north_south + dist->lat;
+ coord->east_west = (1/gradient) * (coord->north_south - from->north_south) + from->north_south;
+ }
+
+ return coord;
+}
+
+static GList *add_fillins(GList *list, VikCoord *from, VikCoord *to, struct LatLon *dist)
+{
+ /* TODO: handle virtical track (to->east_west - from->east_west == 0) */
+ gdouble gradient = (to->north_south - from->north_south)/(to->east_west - from->east_west);
+
+ VikCoord *next = from;
+ while (TRUE) {
+ if ((next = get_next_coord(next, to, dist, gradient)) == NULL)
+ break;
+ list = g_list_prepend(list, next);
+ }
+
+ return list;
+}
+
+void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, gdouble zoom_level)
+{
+ typedef struct _Rect {
+ VikCoord tl;
+ VikCoord br;
+ VikCoord center;
+ } Rect;
+#define GLRECT(iter) ((Rect *)((iter)->data))
+
+ struct LatLon wh;
+ GList *rects_to_download = NULL;
+ GList *rect_iter;
+
+ if (get_download_area_width(vvp, zoom_level, &wh))
+ return;
+
+ GList *iter = tr->trackpoints;
+ if (!iter)
+ return;
+
+ gboolean new_map = TRUE;
+ VikCoord *cur_coord, tl, br;
+ Rect *rect;
+ while (iter) {
+ cur_coord = &(VIK_TRACKPOINT(iter->data))->coord;
+ if (new_map) {
+ vik_coord_set_area(cur_coord, &wh, &tl, &br);
+ rect = g_malloc(sizeof(Rect));
+ rect->tl = tl;
+ rect->br = br;
+ rect->center = *cur_coord;
+ rects_to_download = g_list_prepend(rects_to_download, rect);
+ new_map = FALSE;
+ iter = iter->next;
+ continue;
+ }
+ gboolean found = FALSE;
+ for (rect_iter = rects_to_download; rect_iter; rect_iter = rect_iter->next) {
+ if (vik_coord_inside(cur_coord, &GLRECT(rect_iter)->tl, &GLRECT(rect_iter)->br)) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ iter = iter->next;
+ else
+ 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);
+ }
+ }
+
+ if (fillins) {
+ GList *iter = fillins;
+ while (iter) {
+ cur_coord = (VikCoord *)(iter->data);
+ vik_coord_set_area(cur_coord, &wh, &tl, &br);
+ rect = g_malloc(sizeof(Rect));
+ rect->tl = tl;
+ rect->br = br;
+ rect->center = *cur_coord;
+ rects_to_download = g_list_prepend(rects_to_download, rect);
+ iter = iter->next;
+ }
+ }
+
+ for (rect_iter = rects_to_download; rect_iter; rect_iter = rect_iter->next) {
+ maps_layer_download_section_without_redraw(vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level);
+ }
+
+ if (fillins) {
+ for (iter = fillins; iter; iter = iter->next)
+ g_free(iter->data);
+ g_list_free(fillins);
+ }
+ if (rects_to_download) {
+ for (rect_iter = rects_to_download; rect_iter; rect_iter = rect_iter->next)
+ g_free(rect_iter->data);
+ g_list_free(rects_to_download);
+ }
+}
+
+static void trw_layer_download_map_along_track_cb(gpointer pass_along[6])
+{
+ VikMapsLayer *vml;
+ gint selected_map, default_map;
+ gchar *zoomlist[] = {"0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", NULL };
+ gdouble zoom_vals[] = {0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
+ gint selected_zoom, default_zoom;
+ int i,j;
+
+
+ VikTrwLayer *vtl = pass_along[0];
+ VikLayersPanel *vlp = pass_along[1];
+ VikTrack *tr = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ VikViewport *vvp = vik_window_viewport((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)));
+
+ GList *vmls = vik_layers_panel_get_all_layers_of_type(vlp, VIK_LAYER_MAPS);
+ int num_maps = g_list_length(vmls);
+
+ if (!num_maps) {
+ a_dialog_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), GTK_MESSAGE_ERROR, _("No map layer in use. Create one first"), NULL);
+ return;
+ }
+
+ gchar **map_names = g_malloc(1 + num_maps * sizeof(gpointer));
+ VikMapsLayer **map_layers = g_malloc(1 + num_maps * sizeof(gpointer));
+
+ gchar **np = map_names;
+ VikMapsLayer **lp = map_layers;
+ for (i = 0; i < num_maps; i++) {
+ gboolean dup = FALSE;
+ vml = (VikMapsLayer *)(vmls->data);
+ for (j = 0; j < i; j++) { /* no duplicate allowed */
+ if (vik_maps_layer_get_map_type(vml) == vik_maps_layer_get_map_type(map_layers[j])) {
+ dup = TRUE;
+ break;
+ }
+ }
+ if (!dup) {
+ *lp++ = vml;
+ *np++ = vik_maps_layer_get_map_label(vml);
+ }
+ vmls = vmls->next;
+ }
+ *lp = NULL;
+ *np = NULL;
+ num_maps = lp - map_layers;
+
+ for (default_map = 0; default_map < num_maps; default_map++) {
+ /* TODO: check for parent layer's visibility */
+ if (VIK_LAYER(map_layers[default_map])->visible)
+ break;
+ }
+ default_map = (default_map == num_maps) ? 0 : default_map;
+
+ gdouble cur_zoom = vik_viewport_get_zoom(vvp);
+ for (default_zoom = 0; default_zoom < sizeof(zoom_vals)/sizeof(gdouble); default_zoom++) {
+ if (cur_zoom == zoom_vals[default_zoom])
+ break;
+ }
+ default_zoom = (default_zoom == sizeof(zoom_vals)/sizeof(gdouble)) ? sizeof(zoom_vals)/sizeof(gdouble) - 1 : default_zoom;
+
+ if (!a_dialog_map_n_zoom(VIK_GTK_WINDOW_FROM_LAYER(vtl), map_names, default_map, zoomlist, default_zoom, &selected_map, &selected_zoom))
+ goto done;
+
+ vik_track_download_map(tr, map_layers[selected_map], vvp, zoom_vals[selected_zoom]);
+
+done:
+ for (i = 0; i < num_maps; i++)
+ g_free(map_names[i]);
+ g_free(map_names);
+ g_free(map_layers);
+
+ g_list_free(vmls);
+
+}
+
+/**** lowest waypoint number calculation ***/
+static gint highest_wp_number_name_to_number(const gchar *name) {
+ if ( strlen(name) == 3 ) {
+ int n = atoi(name);
+ if ( n < 100 && name[0] != '0' )
+ return -1;
+ if ( n < 10 && name[0] != '0' )
+ return -1;
+ return n;
+ }
+ return -1;
+}
+
+
+static void highest_wp_number_reset(VikTrwLayer *vtl)
+{
+ vtl->highest_wp_number = -1;
+}
+
+static void highest_wp_number_add_wp(VikTrwLayer *vtl, const gchar *new_wp_name)
+{
+ /* if is bigger that top, add it */
+ gint new_wp_num = highest_wp_number_name_to_number(new_wp_name);
+ if ( new_wp_num > vtl->highest_wp_number )
+ vtl->highest_wp_number = new_wp_num;
+}
+
+static void highest_wp_number_remove_wp(VikTrwLayer *vtl, const gchar *old_wp_name)
+{
+ /* if wasn't top, do nothing. if was top, count backwards until we find one used */
+ gint old_wp_num = highest_wp_number_name_to_number(old_wp_name);
+ if ( vtl->highest_wp_number == old_wp_num ) {
+ gchar buf[4];
+ vtl->highest_wp_number --;
+
+ g_snprintf(buf,4,"%03d", vtl->highest_wp_number );
+ /* search down until we find something that *does* exist */
+
+ while ( vtl->highest_wp_number > 0 && ! g_hash_table_lookup ( vtl->waypoints, buf ) ) {
+ vtl->highest_wp_number --;
+ g_snprintf(buf,4,"%03d", vtl->highest_wp_number );
+ }
+ }
+}
+
+/* get lowest unused number */
+static gchar *highest_wp_number_get(VikTrwLayer *vtl)
+{
+ gchar buf[4];
+ if ( vtl->highest_wp_number < 0 || vtl->highest_wp_number >= 999 )
+ return NULL;
+ g_snprintf(buf,4,"%03d", vtl->highest_wp_number+1 );
+ return g_strdup(buf);
+}