* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-
-#define WAYPOINT_FONT "Sans 8"
-
/* WARNING: If you go beyond this point, we are NOT responsible for any ill effects on your sanity */
-/* viktrwlayer.c -- 5000+ lines can make a difference in the state of things */
+/* viktrwlayer.c -- 8000+ lines can make a difference in the state of things */
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "viking.h"
#include "vikmapslayer.h"
+#include "vikgpslayer.h"
#include "viktrwlayer_tpwin.h"
#include "viktrwlayer_propwin.h"
#ifdef VIK_CONFIG_GEOTAG
#endif
#include "acquire.h"
#include "datasources.h"
+#include "datasource_gps.h"
#include "util.h"
#include "icons/icons.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
-
-#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
-// This is currently broken as Google have disabled the KML output in Google Maps API v3
-// It has been ifdefed out in the hope that Route Finding functionality will be restored one day...
-// Only have 'JSON' and 'XML' see:
-// https://developers.google.com/maps/documentation/directions/#DirectionsResponses
-#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=kml"
+#ifdef VIK_CONFIG_GOOGLE
+#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=js"
#endif
#define VIK_TRW_LAYER_TRACK_GC 16
enum { WP_SYMBOL_FILLED_SQUARE, WP_SYMBOL_SQUARE, WP_SYMBOL_CIRCLE, WP_SYMBOL_X, WP_NUM_SYMBOLS };
+// See http://developer.gnome.org/pango/stable/PangoMarkupFormat.html
+typedef enum {
+ FS_XX_SMALL = 0, // 'xx-small'
+ FS_X_SMALL,
+ FS_SMALL,
+ FS_MEDIUM, // DEFAULT
+ FS_LARGE,
+ FS_X_LARGE,
+ FS_XX_LARGE,
+ FS_NUM_SIZES
+} font_size_t;
+
struct _VikTrwLayer {
VikLayer vl;
GHashTable *tracks;
GHashTable *tracks_iters;
+ GHashTable *routes;
+ GHashTable *routes_iters;
GHashTable *waypoints_iters;
GHashTable *waypoints;
- GtkTreeIter waypoints_iter, tracks_iter;
- gboolean tracks_visible, waypoints_visible;
+ GtkTreeIter tracks_iter, routes_iter, waypoints_iter;
+ gboolean tracks_visible, routes_visible, waypoints_visible;
guint8 drawmode;
guint8 drawpoints;
+ guint8 drawpoints_size;
guint8 drawelevation;
guint8 elevation_factor;
guint8 drawstops;
guint32 stop_length;
guint8 drawlines;
+ guint8 drawdirections;
+ guint8 drawdirections_size;
guint8 line_thickness;
guint8 bg_line_thickness;
guint8 wp_symbol;
guint8 wp_size;
gboolean wp_draw_symbols;
+ font_size_t wp_font_size;
gdouble track_draw_speed_factor;
GArray *track_gc;
GdkGC *waypoint_text_gc;
GdkGC *waypoint_bg_gc;
GdkFont *waypoint_font;
- VikTrack *current_track;
+ VikTrack *current_track; // ATM shared between new tracks and new routes
guint16 ct_x1, ct_y1, ct_x2, ct_y2;
gboolean draw_sync_done;
gboolean draw_sync_do;
VikTrwLayer *vtl;
gdouble xmpp, ympp;
guint16 width, height;
+ gdouble cc; // Cosine factor in track directions
+ gdouble ss; // Sine factor in track directions
const VikCoord *center;
gint track_gc_iter;
gboolean one_zone, lat_lon;
static void trw_layer_cut_item_cb ( gpointer pass_along[6] );
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_tracks ( const gchar *name, const VikTrack *trk, 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_download_map_along_track_cb ( gpointer pass_along[6] );
static void trw_layer_edit_trackpoint ( gpointer pass_along[6] );
static void trw_layer_show_picture ( gpointer pass_along[6] );
+static void trw_layer_gps_upload_any ( gpointer pass_along[6] );
static void trw_layer_centerize ( gpointer layer_and_vlp[2] );
static void trw_layer_auto_view ( gpointer layer_and_vlp[2] );
static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar* title, const gchar* default_name, VikTrack* trk, 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_track ( gpointer lav[2] );
+static void trw_layer_new_route ( gpointer lav[2] );
+static void trw_layer_finish_track ( gpointer lav[2] );
static void trw_layer_auto_waypoints_view ( gpointer lav[2] );
static void trw_layer_auto_tracks_view ( gpointer lav[2] );
static void trw_layer_delete_all_tracks ( gpointer lav[2] );
static void trw_layer_geotagging ( gpointer lav[2] );
#endif
static void trw_layer_acquire_gps_cb ( gpointer lav[2] );
+#ifdef VIK_CONFIG_GOOGLE
static void trw_layer_acquire_google_cb ( gpointer lav[2] );
+#endif
#ifdef VIK_CONFIG_OPENSTREETMAP
static void trw_layer_acquire_osm_cb ( gpointer lav[2] );
#endif
#ifdef VIK_CONFIG_GEOTAG
static void trw_layer_acquire_geotagged_cb ( gpointer lav[2] );
#endif
+static void trw_layer_acquire_file_cb ( gpointer lav[2] );
+static void trw_layer_gps_upload ( gpointer lav[2] );
+
+// Specific route versions:
+// Most track handling functions can handle operating on the route list
+// However these ones are easier in separate functions
+static void trw_layer_auto_routes_view ( gpointer lav[2] );
+static void trw_layer_delete_routes_from_selection ( gpointer lav[2] );
/* pop-up items */
static void trw_layer_properties_item ( gpointer pass_along[7] );
static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer pass_along[5] );
static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pass_along[5] );
-static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp );
+static void init_drawing_params ( struct DrawingParams *dp, VikTrwLayer *vtl, VikViewport *vp );
static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl );
static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy );
static gboolean tool_edit_waypoint_click ( 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_route_create ( VikWindow *vw, VikViewport *vvp);
+static gboolean tool_new_route_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 );
-#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+#ifdef VIK_CONFIG_GOOGLE
static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp);
static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
#endif
TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing
GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf },
- { { "BeginTrack", "vik-icon-Begin Track", N_("_Begin Track"), "<control><shift>B", N_("Begin Track"), 0 },
- (VikToolConstructorFunc) tool_begin_track_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_begin_track_click, NULL, NULL, (VikToolKeyFunc) NULL,
- FALSE,
- GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf },
+ { { "CreateRoute", "vik-icon-Create Route", N_("Create _Route"), "<control><shift>B", N_("Create Route"), 0 },
+ (VikToolConstructorFunc) tool_new_route_create, NULL, NULL, NULL,
+ (VikToolMouseFunc) tool_new_route_click,
+ (VikToolMouseMoveFunc) tool_new_track_move, // -\#
+ (VikToolMouseFunc) tool_new_track_release, // -> Reuse these track methods on a route
+ (VikToolKeyFunc) tool_new_track_key_press, // -/#
+ TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing
+ GDK_CURSOR_IS_PIXMAP, &cursor_new_route_pixbuf },
{ { "EditWaypoint", "vik-icon-Edit Waypoint", N_("_Edit Waypoint"), "<control><shift>E", N_("Edit Waypoint"), 0 },
(VikToolConstructorFunc) tool_edit_waypoint_create, NULL, NULL, NULL,
FALSE,
GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf },
-#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+#ifdef VIK_CONFIG_GOOGLE
{ { "RouteFinder", "vik-icon-Route Finder", N_("Route _Finder"), "<control><shift>F", N_("Route Finder"), 0 },
(VikToolConstructorFunc) tool_route_finder_create, NULL, NULL, NULL,
(VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL,
GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf },
#endif
};
-enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS };
+enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_CREATE_ROUTE, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS };
/****** PARAMETERS ******/
static gchar *params_drawmodes[] = { N_("Draw by Track"), N_("Draw by Speed"), N_("All Tracks Black"), 0 };
static gchar *params_wpsymbols[] = { N_("Filled Square"), N_("Square"), N_("Circle"), N_("X"), 0 };
+#define MIN_POINT_SIZE 2
+#define MAX_POINT_SIZE 10
+
+#define MIN_ARROW_SIZE 3
+#define MAX_ARROW_SIZE 20
static VikLayerParamScale params_scales[] = {
/* min max step digits */
{ 0, 100, 1, 0 }, /* track draw speed factor */
{ 1.0, 100.0, 1.0, 2 }, /* UNUSED */
/* 5 * step == how much to turn */
- { 16, 128, 3.2, 0 }, /* image_size */
- { 0, 255, 5, 0 }, /* image alpha */
- { 5, 500, 5, 0 }, /* image cache_size */
- { 0, 8, 1, 0 }, /* image cache_size */
+ { 16, 128, 4, 0 }, // 3: image_size - NB step size ignored when an HSCALE used
+ { 0, 255, 5, 0 }, // 4: image alpha - " " " "
+ { 5, 500, 5, 0 }, // 5: image cache_size - " "
+ { 0, 8, 1, 0 }, // 6: Background line thickness
{ 1, 64, 1, 0 }, /* wpsize */
{ MIN_STOP_LENGTH, MAX_STOP_LENGTH, 1, 0 }, /* stop_length */
- { 1, 100, 1, 0 }, /* stop_length */
+ { 1, 100, 1, 0 }, // 9: elevation factor
+ { MIN_POINT_SIZE, MAX_POINT_SIZE, 1, 0 }, // 10: track point size
+ { MIN_ARROW_SIZE, MAX_ARROW_SIZE, 1, 0 }, // 11: direction arrow size
};
+static gchar* params_font_sizes[] = {
+ N_("Extra Extra Small"),
+ N_("Extra Small"),
+ N_("Small"),
+ N_("Medium"),
+ N_("Large"),
+ N_("Extra Large"),
+ N_("Extra Extra Large"),
+ NULL };
+
VikLayerParam trw_layer_params[] = {
{ "tracks_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
{ "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
+ { "routes_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
{ "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 },
+ { "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 0 },
+ { "drawdirections", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Direction"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "trkdirectionsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Direction Size:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 11 },
{ "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Trackpoints"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "trkpointsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Trackpoint Size:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 10 },
{ "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 },
- { "speed_factor", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Draw by Speed Factor (%):"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 1 },
+ { "speed_factor", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Draw by Speed Factor (%):"), VIK_LAYER_WIDGET_HSCALE, params_scales + 1 },
{ "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON },
+ { "wpfontsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint Font Size:"), VIK_LAYER_WIDGET_COMBOBOX, params_font_sizes, NULL },
{ "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 },
{ "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_TDSF, 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 };
+// ENUMERATION MUST BE IN THE SAME ORDER AS THE NAMED PARAMS ABOVE
+enum {
+ // Sublayer visibilities
+ PARAM_TV,
+ PARAM_WV,
+ PARAM_RV,
+ // Tracks
+ PARAM_DM,
+ PARAM_DL,
+ PARAM_LT,
+ PARAM_DD,
+ PARAM_DDS,
+ PARAM_DP,
+ PARAM_DPS,
+ PARAM_DE,
+ PARAM_EF,
+ PARAM_DS,
+ PARAM_SL,
+ PARAM_BLT,
+ PARAM_TBGC,
+ PARAM_TDSF,
+ // Waypoints
+ PARAM_DLA,
+ PARAM_WPFONTSIZE,
+ PARAM_WPC,
+ PARAM_WPTC,
+ PARAM_WPBC,
+ PARAM_WPBA,
+ PARAM_WPSYM,
+ PARAM_WPSIZE,
+ PARAM_WPSYMS,
+ // WP images
+ PARAM_DI,
+ PARAM_IS,
+ PARAM_IA,
+ PARAM_ICS,
+ NUM_PARAMS
+};
/*** TO ADD A PARAM:
*** 1) Add to trw_layer_params and enumeration
/* End Layer Interface function definitions */
VikLayerInterface vik_trw_layer_interface = {
+ "TrackWaypoint",
N_("TrackWaypoint"),
"<control><shift>Y",
&viktrwlayer_pixbuf,
else
name = NULL; // Broken :(
}
- else {
+ else if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
VikTrack *trk = g_hash_table_lookup ( vtl->tracks, sublayer);
if ( trk && trk->name )
name = trk->name;
else
name = NULL; // Broken :(
}
+ else {
+ VikTrack *trk = g_hash_table_lookup ( vtl->routes, sublayer);
+ if ( trk && trk->name )
+ name = trk->name;
+ else
+ name = NULL; // Broken :(
+ }
a_clipboard_copy( VIK_CLIPBOARD_DATA_SUBLAYER, VIK_LAYER_TRW,
subtype, len, name, data);
trw_layer_delete_item(pass_along);
}
+static void trw_layer_paste_item_cb ( gpointer pass_along[6])
+{
+ // Slightly cheating method, routing via the panels capability
+ a_clipboard_paste (VIK_LAYERS_PANEL(pass_along[1]));
+}
+
static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len )
{
FlatItem *fi;
fi = g_malloc ( *len );
fi->len = *len;
memcpy(fi->data, id, il);
- } else {
-
+ } else if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
vik_track_marshall ( g_hash_table_lookup ( vtl->tracks, sublayer ), &id, &il );
// less magic than before...
*len = sizeof(FlatItem) + 1 + il;
fi = g_malloc ( *len );
fi->len = *len;
memcpy(fi->data, id, il);
+ } else {
+ vik_track_marshall ( g_hash_table_lookup ( vtl->routes, sublayer ), &id, &il );
+ // less magic than before...
+ *len = sizeof(FlatItem) + 1 + il;
+ fi = g_malloc ( *len );
+ fi->len = *len;
+ memcpy(fi->data, id, il);
}
g_free(id);
// When copying - we'll create a new name based on the original
name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, t->name);
vik_trw_layer_add_track ( vtl, name, t );
- track_convert (name, t, &vtl->coord_mode);
+ vik_track_convert (t, vtl->coord_mode);
// Consider if redraw necessary for the new item
if ( vtl->vl.visible && vtl->tracks_visible && t->visible )
vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
return TRUE;
}
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE && fi )
+ {
+ VikTrack *t;
+ gchar *name;
+
+ t = vik_track_unmarshall(fi->data, fi->len);
+ // When copying - we'll create a new name based on the original
+ name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, t->name);
+ vik_trw_layer_add_route ( vtl, name, t );
+ vik_track_convert (t, vtl->coord_mode);
+
+ // Consider if redraw necessary for the new item
+ if ( vtl->vl.visible && vtl->routes_visible && t->visible )
+ vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ return TRUE;
+ }
return FALSE;
}
{
case PARAM_TV: vtl->tracks_visible = data.b; break;
case PARAM_WV: vtl->waypoints_visible = data.b; break;
+ case PARAM_RV: vtl->routes_visible = data.b; break;
case PARAM_DM: vtl->drawmode = data.u; break;
case PARAM_DP: vtl->drawpoints = data.b; break;
+ case PARAM_DPS:
+ if ( data.u >= MIN_POINT_SIZE && data.u <= MAX_POINT_SIZE )
+ vtl->drawpoints_size = data.u;
+ break;
case PARAM_DE: vtl->drawelevation = data.b; break;
case PARAM_DS: vtl->drawstops = data.b; break;
case PARAM_DL: vtl->drawlines = data.b; break;
+ case PARAM_DD: vtl->drawdirections = data.b; break;
+ case PARAM_DDS:
+ if ( data.u >= MIN_ARROW_SIZE && data.u <= MAX_ARROW_SIZE )
+ vtl->drawdirections_size = data.u;
+ break;
case PARAM_SL: if ( data.u >= MIN_STOP_LENGTH && data.u <= MAX_STOP_LENGTH )
vtl->stop_length = data.u;
break;
case PARAM_WPSYM: if ( data.u < WP_NUM_SYMBOLS ) vtl->wp_symbol = data.u; break;
case PARAM_WPSIZE: if ( data.u > 0 && data.u <= 64 ) vtl->wp_size = data.u; break;
case PARAM_WPSYMS: vtl->wp_draw_symbols = data.b; break;
+ case PARAM_WPFONTSIZE: if ( data.u < FS_NUM_SIZES ) vtl->wp_font_size = data.u; break;
}
return TRUE;
}
{
case PARAM_TV: rv.b = vtl->tracks_visible; break;
case PARAM_WV: rv.b = vtl->waypoints_visible; break;
+ case PARAM_RV: rv.b = vtl->routes_visible; break;
case PARAM_DM: rv.u = vtl->drawmode; break;
case PARAM_DP: rv.b = vtl->drawpoints; break;
+ case PARAM_DPS: rv.u = vtl->drawpoints_size; break;
case PARAM_DE: rv.b = vtl->drawelevation; break;
case PARAM_EF: rv.u = vtl->elevation_factor; break;
case PARAM_DS: rv.b = vtl->drawstops; break;
case PARAM_SL: rv.u = vtl->stop_length; break;
case PARAM_DL: rv.b = vtl->drawlines; break;
+ case PARAM_DD: rv.b = vtl->drawdirections; break;
+ case PARAM_DDS: rv.u = vtl->drawdirections_size; break;
case PARAM_LT: rv.u = vtl->line_thickness; break;
case PARAM_BLT: rv.u = vtl->bg_line_thickness; break;
case PARAM_DLA: rv.b = vtl->drawlabels; break;
case PARAM_WPSYM: rv.u = vtl->wp_symbol; break;
case PARAM_WPSIZE: rv.u = vtl->wp_size; break;
case PARAM_WPSYMS: rv.b = vtl->wp_draw_symbols; break;
+ case PARAM_WPFONTSIZE: rv.u = vtl->wp_font_size; break;
}
return rv;
}
*data = NULL;
if ((f = fdopen(g_file_open_tmp (NULL, &tmpname, NULL), "r+"))) {
- a_gpx_write_file(vtl, f);
+ a_gpx_write_file(vtl, f, NULL);
vik_layer_marshall_params(VIK_LAYER(vtl), &pd, &pl);
fclose(f);
f = NULL;
return rv;
}
-static GList * str_array_to_glist(gchar* data[])
-{
- GList *gl = NULL;
- gpointer * p;
- for (p = (gpointer)data; *p; p++)
- gl = g_list_prepend(gl, *p);
- return(g_list_reverse(gl));
-}
-
// Keep interesting hash function at least visible
/*
static guint strcase_hash(gconstpointer v)
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 );
+ vik_layer_set_type ( VIK_LAYER(rv), VIK_LAYER_TRW );
// It's not entirely clear the benefits of hash tables usage here - possibly the simplicity of first implementation for unique names
// Now with the name of the item stored as part of the item - these tables are effectively straightforward lists
rv->waypoints_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
rv->tracks = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) vik_track_free );
rv->tracks_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
+ rv->routes = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) vik_track_free );
+ rv->routes_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
/* TODO: constants at top */
- rv->waypoints_visible = rv->tracks_visible = TRUE;
+ rv->waypoints_visible = rv->tracks_visible = rv->routes_visible = TRUE;
rv->drawmode = drawmode;
rv->drawpoints = TRUE;
+ rv->drawpoints_size = MIN_POINT_SIZE;
+ rv->drawdirections_size = 5;
rv->drawstops = FALSE;
rv->drawelevation = FALSE;
rv->elevation_factor = 30;
if ( trwlayer->waypoint_bg_gc != NULL )
g_object_unref ( G_OBJECT ( trwlayer->waypoint_bg_gc ) );
- if ( trwlayer->waypoint_font != NULL )
- gdk_font_unref ( trwlayer->waypoint_font );
-
if ( trwlayer->tpwin != NULL )
gtk_widget_destroy ( GTK_WIDGET(trwlayer->tpwin) );
g_queue_free ( trwlayer->image_cache );
}
-static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp )
+static void init_drawing_params ( struct DrawingParams *dp, VikTrwLayer *vtl, VikViewport *vp )
{
+ dp->vtl = vtl;
dp->vp = vp;
dp->xmpp = vik_viewport_get_xmpp ( vp );
dp->ympp = vik_viewport_get_ympp ( vp );
dp->width = vik_viewport_get_width ( vp );
dp->height = vik_viewport_get_height ( vp );
+ dp->cc = vtl->drawdirections_size*cos(45 * DEG2RAD); // Calculate once per vtl update - even if not used
+ dp->ss = vtl->drawdirections_size*sin(45 * DEG2RAD); // Calculate once per vtl update - even if not used
+
dp->center = vik_viewport_get_center ( vp );
dp->one_zone = vik_viewport_is_one_zone ( vp ); /* false if some other projection besides UTM */
dp->lat_lon = vik_viewport_get_coord_mode ( vp ) == VIK_COORD_LATLON;
return VIK_TRW_LAYER_TRACK_GC_BLACK;
}
-void draw_utm_skip_insignia ( VikViewport *vvp, GdkGC *gc, gint x, gint y )
+static void draw_utm_skip_insignia ( VikViewport *vvp, GdkGC *gc, gint x, gint y )
{
vik_viewport_draw_line ( vvp, gc, x+5, y, x-5, y );
vik_viewport_draw_line ( vvp, gc, x, y+5, x, y-5 );
vik_viewport_draw_line ( vvp, gc, x+5, y-5, x-5, y+5 );
}
-static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct DrawingParams *dp, gboolean drawing_white_background )
+static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct DrawingParams *dp, gboolean draw_track_outline )
{
/* TODO: this function is a mess, get rid of any redundancy */
GList *list = track->trackpoints;
gboolean drawelevation;
gdouble min_alt, max_alt, alt_diff = 0;
- const guint8 tp_size_reg = 2;
- const guint8 tp_size_cur = 4;
+ const guint8 tp_size_reg = dp->vtl->drawpoints_size;
+ const guint8 tp_size_cur = dp->vtl->drawpoints_size*2;
guint8 tp_size;
if ( dp->vtl->drawelevation )
return;
/* admittedly this is not an efficient way to do it because we go through the whole GC thing all over... */
- if ( dp->vtl->bg_line_thickness && !drawing_white_background )
+ if ( dp->vtl->bg_line_thickness && !draw_track_outline )
trw_layer_draw_track ( name, track, dp, TRUE );
- if ( drawing_white_background )
+ if ( draw_track_outline )
drawpoints = drawstops = FALSE;
else {
drawpoints = dp->vtl->drawpoints;
then draw in the highlight colour.
NB this supercedes the drawmode */
if ( dp->vtl && ( ( dp->vtl == vik_window_get_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ||
- ( dp->vtl->tracks == vik_window_get_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ||
+ ( !track->is_route && ( dp->vtl->tracks == vik_window_get_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ) ||
+ ( track->is_route && ( dp->vtl->routes == vik_window_get_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ) ||
track == vik_window_get_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ) {
main_gc = vik_viewport_get_gc_highlight (dp->vp);
drawing_highlight = TRUE;
if ( useoldvals && x == oldx && y == oldy )
{
// Still need to process points to ensure 'stops' are drawn if required
- if ( drawstops && drawpoints && ! drawing_white_background && list->next &&
+ if ( drawstops && drawpoints && ! draw_track_outline && list->next &&
(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 );
}
}
- if ( drawpoints && ! drawing_white_background )
+ if ( drawpoints && ! draw_track_outline )
{
if ( list->next ) {
if (!useoldvals)
vik_viewport_coord_to_screen ( dp->vp, &(tp2->coord), &oldx, &oldy );
- if ( drawing_white_background ) {
+ if ( draw_track_outline ) {
vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
}
else {
vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
+
if ( dp->vtl->drawelevation && 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)
}
}
+ if ( (!tp->newsegment) && dp->vtl->drawdirections ) {
+ // Draw an arrow at the mid point to show the direction of the track
+ // Code is a rework from vikwindow::draw_ruler()
+ gint midx = (oldx + x) / 2;
+ gint midy = (oldy + y) / 2;
+
+ gdouble len = sqrt ( ((midx-oldx) * (midx-oldx)) + ((midy-oldy) * (midy-oldy)) );
+ // Avoid divide by zero and ensure at least 1 pixel big
+ if ( len > 1 ) {
+ gdouble dx = (oldx - midx) / len;
+ gdouble dy = (oldy - midy) / len;
+ vik_viewport_draw_line ( dp->vp, main_gc, midx, midy, midx + (dx * dp->cc + dy * dp->ss), midy + (dy * dp->cc - dx * dp->ss) );
+ vik_viewport_draw_line ( dp->vp, main_gc, midx, midy, midx + (dx * dp->cc - dy * dp->ss), midy + (dy * dp->cc + dx * dp->ss) );
+ }
+ }
+
skip:
oldx = x;
oldy = y;
*/
if ( x != oldx || y != oldy )
{
- if ( drawing_white_background )
+ if ( draw_track_outline )
vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
else
vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
/* 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, wp->name, -1 );
+ // Hopefully name won't break the markup (may need to sanitize - g_markup_escape_text())
+
+ // Could this stored in the waypoint rather than recreating each pass?
+ gchar *fsize = NULL;
+ switch (dp->vtl->wp_font_size) {
+ case FS_XX_SMALL: fsize = g_strdup ( "xx-small" ); break;
+ case FS_X_SMALL: fsize = g_strdup ( "x-small" ); break;
+ case FS_SMALL: fsize = g_strdup ( "small" ); break;
+ case FS_LARGE: fsize = g_strdup ( "large" ); break;
+ case FS_X_LARGE: fsize = g_strdup ( "x-large" ); break;
+ case FS_XX_LARGE: fsize = g_strdup ( "xx-large" ); break;
+ default: fsize = g_strdup ( "medium" ); break;
+ }
+
+ gchar *wp_label_markup = g_strdup_printf ( "<span size=\"%s\">%s</span>", fsize, wp->name );
+
+ if ( pango_parse_markup ( wp_label_markup, -1, 0, NULL, NULL, NULL, NULL ) )
+ pango_layout_set_markup ( dp->vtl->wplabellayout, wp_label_markup, -1 );
+ else
+ // Fallback if parse failure
+ pango_layout_set_text ( dp->vtl->wplabellayout, wp->name, -1 );
+
+ g_free ( wp_label_markup );
+ g_free ( fsize );
+
pango_layout_get_pixel_size ( dp->vtl->wplabellayout, &width, &height );
label_x = x - width/2;
if (sym)
static struct DrawingParams dp;
g_assert ( l != NULL );
- init_drawing_params ( &dp, VIK_VIEWPORT(data) );
- dp.vtl = l;
+ init_drawing_params ( &dp, l, VIK_VIEWPORT(data) );
if ( l->tracks_visible )
g_hash_table_foreach ( l->tracks, (GHFunc) trw_layer_draw_track_cb, &dp );
+ if ( l->routes_visible )
+ g_hash_table_foreach ( l->routes, (GHFunc) trw_layer_draw_track_cb, &dp );
+
if (l->waypoints_visible)
g_hash_table_foreach ( l->waypoints, (GHFunc) trw_layer_draw_waypoint, &dp );
}
g_object_unref ( vtl->track_bg_gc );
vtl->track_bg_gc = vik_viewport_new_gc ( vp, "#FFFFFF", width + vtl->bg_line_thickness );
+ // Ensure new track drawing heeds line thickness setting
+ // however always have a minium of 2, as 1 pixel is really narrow
+ gint new_track_width = (vtl->line_thickness < 2) ? 2 : vtl->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->current_track_gc = vik_viewport_new_gc ( vp, "#FF0000", new_track_width );
+ gdk_gc_set_line_attributes ( vtl->current_track_gc, new_track_width, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
// 'newpoint' gc is exactly the same as the current track gc
if ( vtl->current_track_newpoint_gc )
g_object_unref ( vtl->current_track_newpoint_gc );
- vtl->current_track_newpoint_gc = vik_viewport_new_gc ( vp, "#FF0000", 2 );
- gdk_gc_set_line_attributes ( vtl->current_track_newpoint_gc, 2, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
+ vtl->current_track_newpoint_gc = vik_viewport_new_gc ( vp, "#FF0000", new_track_width );
+ gdk_gc_set_line_attributes ( vtl->current_track_newpoint_gc, new_track_width, 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 );
return rv;
}
- 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);
+ pango_layout_set_font_description (rv->wplabellayout, GTK_WIDGET(vp)->style->font_desc);
trw_layer_new_track_gcs ( rv, vp );
rv->waypoint_bg_gc = vik_viewport_new_gc ( vp, "#8383C4", 1 );
gdk_gc_set_function ( rv->waypoint_bg_gc, GDK_AND );
- rv->waypoint_font = gdk_font_load ( "-*-helvetica-bold-r-normal-*-*-100-*-*-p-*-iso8859-1" );
-
rv->has_verified_thumbnails = FALSE;
rv->wp_symbol = WP_SYMBOL_FILLED_SQUARE;
rv->wp_size = 4;
rv->wp_draw_symbols = TRUE;
+ rv->wp_font_size = FS_MEDIUM;
rv->coord_mode = vik_viewport_get_coord_mode ( vp );
return rv;
}
+#define SMALL_ICON_SIZE 18
+/*
+ * Can accept a null symbol, and may return null value
+ */
+static GdkPixbuf* get_wp_sym_small ( gchar *symbol )
+{
+ GdkPixbuf* wp_icon = a_get_wp_sym (symbol);
+ // ATM a_get_wp_sym returns a cached icon, with the size dependent on the preferences.
+ // So needing a small icon for the treeview may need some resizing:
+ if ( wp_icon && gdk_pixbuf_get_width ( wp_icon ) != SMALL_ICON_SIZE )
+ wp_icon = gdk_pixbuf_scale_simple ( wp_icon, SMALL_ICON_SIZE, SMALL_ICON_SIZE, GDK_INTERP_BILINEAR );
+ return wp_icon;
+}
+
static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pass_along[5] )
{
GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter));
#endif
*new_iter = *((GtkTreeIter *) pass_along[1]);
- g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->tracks_iters, id, new_iter );
+ if ( track->is_route )
+ g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->routes_iters, id, new_iter );
+ else
+ g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->tracks_iters, id, new_iter );
if ( ! track->visible )
vik_treeview_item_set_visible ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[1], FALSE );
static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer pass_along[5] )
{
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], wp->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
+ vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], wp->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), get_wp_sym_small (wp->symbol), TRUE, TRUE );
#else
- vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], wp->name, pass_along[2], id, GPOINTER_TO_UINT (pass_along[4]), NULL, TRUE, TRUE );
+ vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], wp->name, pass_along[2], id, GPOINTER_TO_UINT (pass_along[4]), get_wp_sym_small (wp->symbol), TRUE, TRUE );
#endif
*new_iter = *((GtkTreeIter *) pass_along[1]);
vik_treeview_item_set_visible ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[1], FALSE );
}
-
-static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
+static void trw_layer_add_sublayer_tracks ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
{
- GtkTreeIter iter2;
- gpointer pass_along[5] = { &(vtl->tracks_iter), &iter2, vtl, vt, GINT_TO_POINTER(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 );
#else
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 );
+}
+static void trw_layer_add_sublayer_waypoints ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
+{
#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 );
#else
vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->waypoints_iter), _("Waypoints"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINTS, NULL, TRUE, FALSE );
#endif
+}
+
+static void trw_layer_add_sublayer_routes ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
+{
+#ifdef VIK_CONFIG_ALPHABETIZED_TRW
+ vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->routes_iter), _("Routes"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_ROUTES, NULL, TRUE, FALSE );
+#else
+ vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->routes_iter), _("Routes"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_ROUTES, NULL, TRUE, FALSE );
+#endif
+}
+
+static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
+{
+ GtkTreeIter iter2;
+ gpointer pass_along[5] = { &(vtl->tracks_iter), &iter2, vtl, vt, GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_TRACK) };
+
+ if ( g_hash_table_size (vtl->tracks) > 0 ) {
+ trw_layer_add_sublayer_tracks ( vtl, vt , layer_iter );
+ g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_realize_track, pass_along );
+
+ vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->tracks_iter), vtl->tracks_visible );
+ }
+
+ if ( g_hash_table_size (vtl->routes) > 0 ) {
+
+ trw_layer_add_sublayer_routes ( vtl, vt, layer_iter );
- if ( ! vtl->waypoints_visible )
- vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->waypoints_iter), FALSE );
+ pass_along[0] = &(vtl->routes_iter);
+ pass_along[4] = GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_ROUTE);
- pass_along[0] = &(vtl->waypoints_iter);
- pass_along[4] = GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
+ g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_realize_track, pass_along );
- g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_realize_waypoint, pass_along );
+ vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->routes_iter), vtl->routes_visible );
+ }
+
+ if ( g_hash_table_size (vtl->waypoints) > 0 ) {
+ trw_layer_add_sublayer_waypoints ( vtl, vt, layer_iter );
+
+ pass_along[0] = &(vtl->waypoints_iter);
+ pass_along[4] = GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
+
+ g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_realize_waypoint, pass_along );
+
+ vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->waypoints_iter), vtl->waypoints_visible );
+ }
}
{
case VIK_TRW_LAYER_SUBLAYER_TRACKS: return (l->tracks_visible ^= 1);
case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: return (l->waypoints_visible ^= 1);
+ case VIK_TRW_LAYER_SUBLAYER_ROUTES: return (l->routes_visible ^= 1);
case VIK_TRW_LAYER_SUBLAYER_TRACK:
{
VikTrack *t = g_hash_table_lookup ( l->tracks, sublayer );
else
return TRUE;
}
+ case VIK_TRW_LAYER_SUBLAYER_ROUTE:
+ {
+ VikTrack *t = g_hash_table_lookup ( l->routes, sublayer );
+ if (t)
+ return (t->visible ^= 1);
+ else
+ return TRUE;
+ }
}
return TRUE;
}
// Put together all the elements to form compact tooltip text
g_snprintf (tmp_buf, sizeof(tmp_buf),
- _("Tracks: %d - Waypoints: %d%s"),
- g_hash_table_size (vtl->tracks), g_hash_table_size (vtl->waypoints), tbuf2);
+ _("Tracks: %d - Waypoints: %d - Routes: %d%s"),
+ g_hash_table_size (vtl->tracks), g_hash_table_size (vtl->waypoints), g_hash_table_size (vtl->routes), tbuf2);
g_date_free (gdate_start);
g_date_free (gdate_end);
{
switch ( subtype )
{
- case VIK_TRW_LAYER_SUBLAYER_TRACKS: return NULL;
- case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: return NULL;
+ case VIK_TRW_LAYER_SUBLAYER_TRACKS:
+ {
+ // Very simple tooltip - may expand detail in the future...
+ static gchar tmp_buf[32];
+ g_snprintf (tmp_buf, sizeof(tmp_buf),
+ _("Tracks: %d"),
+ g_hash_table_size (l->tracks));
+ return tmp_buf;
+ }
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_ROUTES:
+ {
+ // Very simple tooltip - may expand detail in the future...
+ static gchar tmp_buf[32];
+ g_snprintf (tmp_buf, sizeof(tmp_buf),
+ _("Routes: %d"),
+ g_hash_table_size (l->routes));
+ return tmp_buf;
+ }
+ break;
+
+ case VIK_TRW_LAYER_SUBLAYER_ROUTE:
+ // Same tooltip for a route
case VIK_TRW_LAYER_SUBLAYER_TRACK:
{
- VikTrack *tr = g_hash_table_lookup ( l->tracks, sublayer );
+ VikTrack *tr;
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ tr = g_hash_table_lookup ( l->tracks, sublayer );
+ else
+ tr = g_hash_table_lookup ( l->routes, sublayer );
+
if ( tr ) {
// Could be a better way of handling strings - but this works...
gchar time_buf1[20];
}
}
break;
+ case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS:
+ {
+ // Very simple tooltip - may expand detail in the future...
+ static gchar tmp_buf[32];
+ g_snprintf (tmp_buf, sizeof(tmp_buf),
+ _("Waypoints: %d"),
+ g_hash_table_size (l->waypoints));
+ return tmp_buf;
+ }
+ break;
case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
{
VikWaypoint *w = g_hash_table_lookup ( l->waypoints, sublayer );
case VIK_TRW_LAYER_SUBLAYER_TRACK:
{
VikTrack *track = g_hash_table_lookup ( l->tracks, sublayer );
- vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)track, l, sublayer );
+ vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)track, l );
+ /* Mark for redraw */
+ return TRUE;
+ }
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_ROUTES:
+ {
+ vik_window_set_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->routes, l );
+ /* Mark for redraw */
+ return TRUE;
+ }
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_ROUTE:
+ {
+ VikTrack *track = g_hash_table_lookup ( l->routes, sublayer );
+ vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)track, l );
/* Mark for redraw */
return TRUE;
}
break;
case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
{
- VikWaypoint *wpt = g_hash_table_lookup ( l->waypoints, sublayer );
- if ( wpt ) {
- vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)wpt, l, sublayer );
- // Show some waypoint info
- set_statusbar_msg_info_wpt ( l, wpt );
- /* Mark for redraw */
- return TRUE;
- }
+ VikWaypoint *wpt = g_hash_table_lookup ( l->waypoints, sublayer );
+ if ( wpt ) {
+ vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)wpt, l );
+ // Show some waypoint info
+ set_statusbar_msg_info_wpt ( l, wpt );
+ /* Mark for redraw */
+ return TRUE;
+ }
}
break;
default:
return l->tracks;
}
+GHashTable *vik_trw_layer_get_routes ( VikTrwLayer *l )
+{
+ return l->routes;
+}
+
GHashTable *vik_trw_layer_get_waypoints ( VikTrwLayer *l )
{
return l->waypoints;
return g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find, (gpointer) name );
}
+/*
+ * Get route by name - not guaranteed to be unique
+ * Finds the first one
+ */
+VikTrack *vik_trw_layer_get_route ( VikTrwLayer *vtl, const gchar *name )
+{
+ return g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find, (gpointer) name );
+}
+
static void trw_layer_find_maxmin_waypoints ( const gchar *name, const VikWaypoint *w, struct LatLon maxmin[2] )
{
static VikCoord fixme;
maxmin[1].lon = VIK_LATLON(&fixme)->lon;
}
-static void trw_layer_find_maxmin_tracks ( const gchar *name, GList **t, struct LatLon maxmin[2] )
+static void trw_layer_find_maxmin_tracks ( const gchar *name, const VikTrack *trk, struct LatLon maxmin[2] )
{
- GList *tr = *t;
+ GList *tr = trk->trackpoints;
static VikCoord fixme;
while ( tr )
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;
- }
+ // Continually reuse maxmin to find the latest maximum and minimum values
+ 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 );
+ g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_find_maxmin_tracks, maxmin );
}
gboolean vik_trw_layer_find_center ( VikTrwLayer *vtl, VikCoord *dest )
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, trk );
+ failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE );
break;
}
else
if ( a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
{
gtk_widget_hide ( file_selector );
- failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk );
+ failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE );
break;
}
}
int fd;
if ((fd = g_file_open_tmp("tmp-viking.XXXXXX.gpx", &name_used, NULL)) >= 0) {
- gboolean failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), name_used, FILE_TYPE_GPX, NULL);
+ gboolean failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), name_used, FILE_TYPE_GPX, NULL, TRUE);
if (failed) {
a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("Could not create temporary file for export.") );
}
gpointer layer_and_vlp[2];
layer_and_vlp[0] = pass_along[0];
layer_and_vlp[1] = pass_along[1];
- VikTrack *trk = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+
+ VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+ VikTrack *trk;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
if ( !trk || !trk->name )
return;
a_acquire ( vw, vlp, vvp, &vik_datasource_gps_interface );
}
+#ifdef VIK_CONFIG_GOOGLE
/*
* Acquire into this TRW Layer from Google Directions
*/
a_acquire ( vw, vlp, vvp, &vik_datasource_google_interface );
}
+#endif
#ifdef VIK_CONFIG_OPENSTREETMAP
/*
}
#endif
+static void trw_layer_gps_upload ( gpointer lav[2] )
+{
+ gpointer pass_along[6];
+ pass_along[0] = lav[0];
+ pass_along[1] = lav[1];
+ pass_along[2] = NULL; // No track - operate on the layer
+ pass_along[3] = NULL;
+ pass_along[4] = NULL;
+ pass_along[5] = NULL;
+
+ trw_layer_gps_upload_any ( pass_along );
+}
+
+/**
+ * If pass_along[3] is defined that this will upload just that track
+ */
+static void trw_layer_gps_upload_any ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+ VikLayersPanel *vlp = VIK_LAYERS_PANEL(pass_along[1]);
+
+ // May not actually get a track here as pass_along[2&3] can be null
+ VikTrack *track = NULL;
+ vik_gps_xfer_type xfer_type = TRK; // VIK_TRW_LAYER_SUBLAYER_TRACKS = 0 so hard to test different from NULL!
+ gboolean xfer_all = FALSE;
+
+ if ( pass_along[2] ) {
+ xfer_all = FALSE;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ xfer_type = RTE;
+ }
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ xfer_type = TRK;
+ }
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS ) {
+ xfer_type = WPT;
+ }
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTES ) {
+ xfer_type = RTE;
+ }
+ }
+ else if ( !pass_along[4] )
+ xfer_all = TRUE; // i.e. whole layer
+
+ if (track && !track->visible) {
+ a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Can not upload invisible track.") );
+ return;
+ }
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons ( _("GPS Upload"),
+ VIK_GTK_WINDOW_FROM_LAYER(pass_along[0]),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT,
+ NULL );
+
+ gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
+ GtkWidget *response_w = NULL;
+#if GTK_CHECK_VERSION (2, 20, 0)
+ response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
+#endif
+
+ if ( response_w )
+ gtk_widget_grab_focus ( response_w );
+
+ gpointer dgs = datasource_gps_setup ( dialog, xfer_type, xfer_all );
+
+ if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
+ datasource_gps_clean_up ( dgs );
+ gtk_widget_destroy ( dialog );
+ return;
+ }
+
+ // Get info from reused datasource dialog widgets
+ gchar* protocol = datasource_gps_get_protocol ( dgs );
+ gchar* port = datasource_gps_get_descriptor ( dgs );
+ // NB don't free the above strings as they're references to values held elsewhere
+ gboolean do_tracks = datasource_gps_get_do_tracks ( dgs );
+ gboolean do_routes = datasource_gps_get_do_routes ( dgs );
+ gboolean do_waypoints = datasource_gps_get_do_waypoints ( dgs );
+ gboolean turn_off = datasource_gps_get_off ( dgs );
+
+ gtk_widget_destroy ( dialog );
+
+ // When called from the viewport - work the corresponding layerspanel:
+ if ( !vlp ) {
+ vlp = vik_window_layers_panel ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
+ }
+
+ // Apply settings to transfer to the GPS device
+ vik_gps_comm ( vtl,
+ track,
+ GPS_UP,
+ protocol,
+ port,
+ FALSE,
+ vik_layers_panel_get_viewport (vlp),
+ vlp,
+ do_tracks,
+ do_routes,
+ do_waypoints,
+ turn_off );
+}
+
+/*
+ * Acquire into this TRW Layer from any GPS Babel supported file
+ */
+static void trw_layer_acquire_file_cb ( gpointer lav[2] )
+{
+ 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);
+
+ a_acquire ( vw, vlp, vvp, &vik_datasource_file_interface );
+}
+
static void trw_layer_new_wp ( gpointer lav[2] )
{
VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
vik_layers_panel_emit_update ( vlp );
}
+static void trw_layer_new_track ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+
+ if ( ! vtl->current_track ) {
+ gchar *name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, _("Track")) ;
+ vtl->current_track = vik_track_new();
+ vtl->current_track->visible = TRUE;
+ vik_trw_layer_add_track ( vtl, name, vtl->current_track );
+
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK );
+ }
+}
+
+static void trw_layer_new_route ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+
+ if ( ! vtl->current_track ) {
+ gchar *name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, _("Route")) ;
+ vtl->current_track = vik_track_new();
+ vtl->current_track->visible = TRUE;
+ vtl->current_track->is_route = TRUE;
+ vik_trw_layer_add_route ( vtl, name, vtl->current_track );
+
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_ROUTE );
+ }
+}
+
+static void trw_layer_auto_routes_view ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+
+ if ( g_hash_table_size (vtl->routes) > 0 ) {
+ struct LatLon maxmin[2] = { {0,0}, {0,0} };
+ g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_find_maxmin_tracks, maxmin );
+ trw_layer_zoom_to_show_latlons ( vtl, vik_layers_panel_get_viewport (vlp), maxmin );
+ vik_layers_panel_emit_update ( vlp );
+ }
+}
+
+
+static void trw_layer_finish_track ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ vtl->current_track = NULL;
+ vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+}
+
static void trw_layer_auto_tracks_view ( gpointer lav[2] )
{
VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
+ if ( vtl->current_track ) {
+ if ( vtl->current_track->is_route )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Route") );
+ else
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Track") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
/* Now with icons */
item = gtk_image_menu_item_new_with_mnemonic ( _("_View Layer") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("View All Trac_ks") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_tracks_view), pass_along );
+ GtkWidget *view_submenu = gtk_menu_new();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("V_iew") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU) );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), view_submenu );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("View All _Tracks") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_tracks_view), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (view_submenu), item);
+ gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("View All _Routes") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_routes_view), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (view_submenu), item);
+ gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("V_iew All Waypoints") );
+ item = gtk_menu_item_new_with_mnemonic ( _("View All _Waypoints") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_waypoints_view), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (view_submenu), item);
gtk_widget_show ( item );
item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Center of Layer") );
gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_New Waypoint...") );
+ GtkWidget *new_submenu = gtk_menu_new();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_New") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ gtk_menu_shell_append(GTK_MENU_SHELL (menu), item);
+ gtk_widget_show(item);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), new_submenu);
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("New _Waypoint...") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
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_menu_shell_append (GTK_MENU_SHELL (new_submenu), item);
gtk_widget_show ( item );
-#ifdef VIK_CONFIG_GEONAMES
- GtkWidget *wikipedia_submenu = gtk_menu_new();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("New _Track") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), item);
+ gtk_widget_show ( item );
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(vtl->current_track) );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("New _Route") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_route), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), item);
+ gtk_widget_show ( item );
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(vtl->current_track) );
+
+#ifdef VIK_CONFIG_GEONAMES
+ GtkWidget *wikipedia_submenu = gtk_menu_new();
item = gtk_image_menu_item_new_with_mnemonic ( _("_Add Wikipedia Waypoints") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
gtk_menu_shell_append(GTK_MENU_SHELL (menu), item);
gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
gtk_widget_show ( item );
+#ifdef VIK_CONFIG_GOOGLE
item = gtk_menu_item_new_with_mnemonic ( _("From G_oogle Directions...") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_google_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
gtk_widget_show ( item );
+#endif
#ifdef VIK_CONFIG_OPENSTREETMAP
item = gtk_menu_item_new_with_mnemonic ( _("From _OSM Traces...") );
gtk_widget_show ( item );
#endif
+ item = gtk_menu_item_new_with_mnemonic ( _("From _File...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_file_cb), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+ gtk_widget_show ( item );
+
+ GtkWidget *upload_submenu = gtk_menu_new ();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Upload") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), upload_submenu );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _GPS...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_gps_upload), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (upload_submenu), item);
+ gtk_widget_show ( item );
+
#ifdef VIK_CONFIG_OPENSTREETMAP
item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
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_menu_shell_append (GTK_MENU_SHELL (upload_submenu), item);
gtk_widget_show ( item );
#endif
if ( VIK_LAYER(vtl)->realized )
{
+ // Do we need to create the sublayer:
+ if ( g_hash_table_size (vtl->waypoints) == 0 ) {
+ trw_layer_add_sublayer_waypoints ( vtl, VIK_LAYER(vtl)->vt, &(VIK_LAYER(vtl)->iter) );
+ }
+
GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
// Visibility column always needed for waypoints
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
- vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, NULL, TRUE, TRUE );
+ vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, get_wp_sym_small (wp->symbol), TRUE, TRUE );
#else
- vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, NULL, TRUE, TRUE );
+ vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, get_wp_sym_small (wp->symbol), TRUE, TRUE );
#endif
// Actual setting of visibility dependent on the waypoint
vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, wp->visible );
if ( VIK_LAYER(vtl)->realized )
{
+ // Do we need to create the sublayer:
+ if ( g_hash_table_size (vtl->tracks) == 0 ) {
+ trw_layer_add_sublayer_tracks ( vtl, VIK_LAYER(vtl)->vt, &(VIK_LAYER(vtl)->iter) );
+ }
+
GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
// Visibility column always needed for tracks
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
}
+// Fake Route UUIDs vi simple increasing integer
+static guint rt_uuid = 0;
+
+void vik_trw_layer_add_route ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
+{
+ rt_uuid++;
+
+ vik_track_set_name (t, name);
+
+ if ( VIK_LAYER(vtl)->realized )
+ {
+ // Do we need to create the sublayer:
+ if ( g_hash_table_size (vtl->routes) == 0 ) {
+ trw_layer_add_sublayer_routes ( vtl, VIK_LAYER(vtl)->vt, &(VIK_LAYER(vtl)->iter) );
+ }
+
+ GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
+ // Visibility column always needed for tracks
+#ifdef VIK_CONFIG_ALPHABETIZED_TRW
+ vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), iter, name, vtl, GUINT_TO_POINTER(rt_uuid), VIK_TRW_LAYER_SUBLAYER_ROUTE, NULL, TRUE, TRUE );
+#else
+ vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), iter, name, vtl, GUINT_TO_POINTER(rt_uuid), VIK_TRW_LAYER_SUBLAYER_ROUTE, NULL, TRUE, TRUE );
+#endif
+ // Actual setting of visibility dependent on the track
+ vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, t->visible );
+
+ g_hash_table_insert ( vtl->routes_iters, GUINT_TO_POINTER(rt_uuid), iter );
+ }
+
+ g_hash_table_insert ( vtl->routes, GUINT_TO_POINTER(rt_uuid), t );
+
+}
+
/* to be called whenever a track has been deleted or may have been changed. */
void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, VikTrack *trk )
{
if (vtl->current_tp_track == trk )
trw_layer_cancel_current_tp ( vtl, FALSE );
}
-
+
gchar *trw_layer_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name)
{
- gint i = 2;
- gchar *newname = g_strdup(name);
- while ((sublayer_type == VIK_TRW_LAYER_SUBLAYER_TRACK) ?
- (void *)vik_trw_layer_get_track(vtl, newname) : (void *)vik_trw_layer_get_waypoint(vtl, newname)) {
- gchar *new_newname = g_strdup_printf("%s#%d", name, i);
- g_free(newname);
- newname = new_newname;
- i++;
- }
+ gint i = 2;
+ gchar *newname = g_strdup(name);
+
+ gpointer id = NULL;
+ do {
+ id = NULL;
+ switch ( sublayer_type ) {
+ case VIK_TRW_LAYER_SUBLAYER_TRACK:
+ id = (gpointer) vik_trw_layer_get_track ( vtl, newname );
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
+ id = (gpointer) vik_trw_layer_get_waypoint ( vtl, newname );
+ break;
+ default:
+ id = (gpointer) vik_trw_layer_get_route ( vtl, newname );
+ break;
+ }
+ // If found a name already in use try adding 1 to it and we try again
+ if ( id ) {
+ gchar *new_newname = g_strdup_printf("%s#%d", name, i);
+ g_free(newname);
+ newname = new_newname;
+ i++;
+ }
+ } while ( id != NULL);
+
return newname;
}
} else {
// No more uniqueness of name forced when loading from a file
- vik_trw_layer_add_track ( vtl, name, tr );
+ if ( tr->is_route )
+ vik_trw_layer_add_route ( vtl, name, tr );
+ else
+ vik_trw_layer_add_track ( vtl, name, tr );
if ( vtl->route_finder_check_added_track ) {
vik_track_remove_dup_points ( tr ); /* make "double point" track work to undo */
vik_trw_layer_delete_track ( vtl_src, trk );
}
+ if (type == VIK_TRW_LAYER_SUBLAYER_ROUTE) {
+ VikTrack *trk = g_hash_table_lookup ( vtl_src->routes, id );
+
+ gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, trk->name);
+
+ VikTrack *trk2 = vik_track_copy ( trk );
+ vik_trw_layer_add_route ( vtl_dest, newname, trk2 );
+ vik_trw_layer_delete_route ( vtl_src, trk );
+ }
+
if (type == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) {
VikWaypoint *wp = g_hash_table_lookup ( vtl_src->waypoints, id );
if (type==VIK_TRW_LAYER_SUBLAYER_WAYPOINTS) {
g_hash_table_foreach ( vtl_src->waypoints, (GHFunc)trw_layer_enum_item, &items);
}
-
+ if (type==VIK_TRW_LAYER_SUBLAYER_ROUTES) {
+ g_hash_table_foreach ( vtl_src->routes, (GHFunc)trw_layer_enum_item, &items);
+ }
+
iter = items;
while (iter) {
if (type==VIK_TRW_LAYER_SUBLAYER_TRACKS) {
- trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_TRACK);
+ trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_TRACK);
+ }
+ else if (type==VIK_TRW_LAYER_SUBLAYER_ROUTES) {
+ trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_ROUTE);
} else {
- trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
+ trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
}
iter = iter->next;
}
vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
g_hash_table_remove ( vtl->tracks_iters, udata.uuid );
g_hash_table_remove ( vtl->tracks, udata.uuid );
+
+ // If last sublayer, then remove sublayer container
+ if ( g_hash_table_size (vtl->tracks) == 0 ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter) );
+ }
+ }
+ }
+ }
+ return was_visible;
+}
+
+gboolean vik_trw_layer_delete_route ( VikTrwLayer *vtl, VikTrack *trk )
+{
+ gboolean was_visible = FALSE;
+
+ if ( trk && trk->name ) {
+
+ if ( trk == vtl->current_track ) {
+ vtl->current_track = NULL;
+ vtl->current_tp_track = NULL;
+ vtl->current_tp_id = NULL;
+ vtl->moving_tp = FALSE;
+ }
+
+ was_visible = trk->visible;
+
+ if ( trk == vtl->route_finder_current_track )
+ vtl->route_finder_current_track = NULL;
+
+ if ( trk == vtl->route_finder_added_track )
+ vtl->route_finder_added_track = NULL;
+
+ trku_udata udata;
+ udata.trk = trk;
+ udata.uuid = NULL;
+
+ // Hmmm, want key of it
+ gpointer *trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
+
+ if ( trkf && udata.uuid ) {
+ /* could be current_tp, so we have to check */
+ trw_layer_cancel_tps_of_track ( vtl, trk );
+
+ GtkTreeIter *it = g_hash_table_lookup ( vtl->routes_iters, udata.uuid );
+
+ if ( it ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
+ g_hash_table_remove ( vtl->routes_iters, udata.uuid );
+ g_hash_table_remove ( vtl->routes, udata.uuid );
+
+ // If last sublayer, then remove sublayer container
+ if ( g_hash_table_size (vtl->routes) == 0 ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter) );
+ }
}
}
}
highest_wp_number_remove_wp(vtl, wp->name);
g_hash_table_remove ( vtl->waypoints, udata.uuid ); // last because this frees the name
+
+ // If last sublayer, then remove sublayer container
+ if ( g_hash_table_size (vtl->waypoints) == 0 ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter) );
+ }
}
}
/*
* Delete a track by the given name
* NOTE: ATM this will delete the first encountered Track with the specified name
- * as there be multiple track with the same name
+ * as there may be multiple tracks with the same name within the specified hash table
*/
-static gboolean trw_layer_delete_track_by_name ( VikTrwLayer *vtl, const gchar *name )
+static gboolean trw_layer_delete_track_by_name ( VikTrwLayer *vtl, const gchar *name, GHashTable *ht_tracks )
{
tpu_udata udata;
// Fake a track with the given name
udata.uuid = NULL;
// Hmmm, want key of it
- gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid_by_name, &udata );
+ gpointer *trkf = g_hash_table_find ( ht_tracks, (GHRFunc) trw_layer_track_find_uuid_by_name, &udata );
vik_track_free (udata.trk);
- if ( trkf && udata.uuid )
- return vik_trw_layer_delete_track (vtl, g_hash_table_lookup ( vtl->tracks, udata.uuid ));
+ if ( trkf && udata.uuid ) {
+ // This could be a little better written...
+ if ( vtl->tracks == ht_tracks )
+ return vik_trw_layer_delete_track (vtl, g_hash_table_lookup ( ht_tracks, udata.uuid ));
+ if ( vtl->routes == ht_tracks )
+ return vik_trw_layer_delete_route (vtl, g_hash_table_lookup ( ht_tracks, udata.uuid ));
+ return FALSE;
+ }
else
return FALSE;
}
vik_treeview_item_delete (vt, it );
}
+void vik_trw_layer_delete_all_routes ( VikTrwLayer *vtl )
+{
+
+ vtl->current_track = NULL;
+ vtl->route_finder_current_track = NULL;
+ vtl->route_finder_added_track = NULL;
+ if (vtl->current_tp_track)
+ trw_layer_cancel_current_tp(vtl, FALSE);
+
+ g_hash_table_foreach(vtl->routes_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
+ g_hash_table_remove_all(vtl->routes_iters);
+ g_hash_table_remove_all(vtl->routes);
+
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter) );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+}
+
void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
{
g_hash_table_remove_all(vtl->tracks_iters);
g_hash_table_remove_all(vtl->tracks);
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter) );
+
vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
}
g_hash_table_remove_all(vtl->waypoints_iters);
g_hash_table_remove_all(vtl->waypoints);
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter) );
+
vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
}
vik_trw_layer_delete_all_tracks (vtl);
}
+static void trw_layer_delete_all_routes ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ // Get confirmation from the user
+ if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Are you sure you want to delete all routes in %s?"),
+ vik_layer_get_name ( VIK_LAYER(vtl) ) ) )
+ vik_trw_layer_delete_all_routes (vtl);
+}
+
static void trw_layer_delete_all_waypoints ( gpointer lav[2] )
{
VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
was_visible = trw_layer_delete_waypoint ( vtl, wp );
}
}
- else
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_TRACK )
{
VikTrack *trk = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
if ( trk && trk->name ) {
was_visible = vik_trw_layer_delete_track ( vtl, trk );
}
}
+ else
+ {
+ VikTrack *trk = g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ if ( trk && trk->name ) {
+ if ( GPOINTER_TO_INT ( pass_along[4]) )
+ // Get confirmation from the user
+ if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Are you sure you want to delete the route \"%s\""),
+ trk->name ) )
+ return;
+ was_visible = vik_trw_layer_delete_route ( vtl, trk );
+ }
+ }
if ( was_visible )
vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
}
gboolean updated = FALSE;
a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wp->name, wp, vtl->coord_mode, FALSE, &updated );
+ if ( updated && pass_along[6] )
+ vik_treeview_item_set_icon ( VIK_LAYER(vtl)->vt, pass_along[6], get_wp_sym_small (wp->symbol) );
+
if ( updated && VIK_LAYER(vtl)->visible )
vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
}
}
else
{
- VikTrack *tr = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *tr;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ tr = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ else
+ tr = g_hash_table_lookup ( vtl->routes, pass_along[3] );
+
if ( tr && tr->name )
{
vik_trw_layer_propwin_run ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
static void trw_layer_goto_track_startpoint ( gpointer pass_along[6] )
{
- GList *trps = ((VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ))->trackpoints;
- if ( trps && trps->data )
- goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *) trps->data)->coord));
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( track && track->trackpoints )
+ goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *) track->trackpoints->data)->coord) );
}
static void trw_layer_goto_track_center ( gpointer pass_along[6] )
{
- /* 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 )
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( track && track->trackpoints )
{
struct LatLon average, maxmin[2] = { {0,0}, {0,0} };
VikCoord coord;
- trw_layer_find_maxmin_tracks ( NULL, trps, maxmin );
+ trw_layer_find_maxmin_tracks ( NULL, track, maxmin );
average.lat = (maxmin[0].lat+maxmin[1].lat)/2;
average.lon = (maxmin[0].lon+maxmin[1].lon)/2;
- vik_coord_load_from_latlon ( &coord, VIK_TRW_LAYER(pass_along[0])->coord_mode, &average );
+ vik_coord_load_from_latlon ( &coord, vtl->coord_mode, &average );
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &coord);
}
}
+static void trw_layer_convert_track_route ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ // Converting a track to a route can be a bit more complicated,
+ // so give a chance to change our minds:
+ if ( !trk->is_route &&
+ ( ( vik_track_get_segment_count ( trk ) > 1 ) ||
+ ( vik_track_get_average_speed ( trk ) > 0.0 ) ) ) {
+
+ if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Converting a track to a route removes extra track data such as segments, timestamps, etc...\nDo you want to continue?"), NULL ) )
+ return;
+}
+
+ // Copy it
+ VikTrack *trk_copy = vik_track_copy ( trk );
+
+ // Convert
+ trk_copy->is_route = !trk_copy->is_route;
+
+ // ATM can't set name to self - so must create temporary copy
+ gchar *name = g_strdup ( trk_copy->name );
+
+ // Delete old one and then add new one
+ if ( trk->is_route ) {
+ vik_trw_layer_delete_route ( vtl, trk );
+ vik_trw_layer_add_track ( vtl, name, trk_copy );
+ }
+ else {
+ // Extra route conversion bits...
+ vik_track_merge_segments ( trk_copy );
+ vik_track_to_routepoints ( trk_copy );
+
+ vik_trw_layer_delete_track ( vtl, trk );
+ vik_trw_layer_add_route ( vtl, name, trk_copy );
+ }
+ g_free ( name );
+
+ // Update in case color of track / route changes when moving between sublayers
+ vik_layer_emit_update ( VIK_LAYER(pass_along[0]), FALSE );
+}
+
+
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] );
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
vtl->current_track = track;
- vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK);
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, track->is_route ? TOOL_CREATE_ROUTE : TOOL_CREATE_TRACK);
if ( track->trackpoints )
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) );
}
-#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+#ifdef VIK_CONFIG_GOOGLE
/**
* extend a track using route finder
*/
{
/* 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] );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
- vik_track_apply_dem_data ( track );
+ if ( track )
+ 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;
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ GList *trps = track->trackpoints;
if ( !trps )
return;
trps = g_list_last(trps);
static void trw_layer_goto_track_max_speed ( gpointer pass_along[6] )
{
- VikTrackpoint* vtp = vik_track_get_tp_by_max_speed ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ VikTrackpoint* vtp = vik_track_get_tp_by_max_speed ( track );
if ( !vtp )
return;
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
static void trw_layer_goto_track_max_alt ( gpointer pass_along[6] )
{
- VikTrackpoint* vtp = vik_track_get_tp_by_max_alt ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ VikTrackpoint* vtp = vik_track_get_tp_by_max_alt ( track );
if ( !vtp )
return;
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] )
{
- VikTrackpoint* vtp = vik_track_get_tp_by_min_alt ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ VikTrackpoint* vtp = vik_track_get_tp_by_min_alt ( track );
if ( !vtp )
return;
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
*/
static void trw_layer_auto_track_view ( gpointer pass_along[6] )
{
- GList **trps = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
- if ( trps && *trps )
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( trk && trk->trackpoints )
{
struct LatLon maxmin[2] = { {0,0}, {0,0} };
- trw_layer_find_maxmin_tracks ( NULL, trps, maxmin );
+ trw_layer_find_maxmin_tracks ( NULL, trk, maxmin );
trw_layer_zoom_to_show_latlons ( VIK_TRW_LAYER(pass_along[0]), pass_along[5], maxmin );
if ( pass_along[1] )
vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(pass_along[1]) );
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
GList *other_tracks = NULL;
- VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ GHashTable *ght_tracks;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ ght_tracks = vtl->routes;
+ else
+ ght_tracks = vtl->tracks;
+
+ VikTrack *track = (VikTrack *) g_hash_table_lookup ( ght_tracks, pass_along[3] );
+
+ if ( !track )
+ return;
if ( !track->trackpoints )
return;
// i.e. either those times, or those without
udata.with_timestamps = (VIK_TRACKPOINT(track->trackpoints->data)->has_timestamp);
- g_hash_table_foreach(vtl->tracks, find_tracks_with_timestamp_type, (gpointer)&udata);
+ g_hash_table_foreach(ght_tracks, find_tracks_with_timestamp_type, (gpointer)&udata);
other_tracks = g_list_reverse(other_tracks);
if ( !other_tracks ) {
GList *other_tracks_names = NULL;
GList *iter = g_list_first ( other_tracks );
while ( iter ) {
- other_tracks_names = g_list_append ( other_tracks_names, VIK_TRACK(g_hash_table_lookup (vtl->tracks, iter->data))->name );
+ other_tracks_names = g_list_append ( other_tracks_names, VIK_TRACK(g_hash_table_lookup (ght_tracks, iter->data))->name );
iter = g_list_next ( iter );
}
other_tracks_names = g_list_sort_with_data (other_tracks_names, sort_alphabetically, NULL);
GList *merge_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
- other_tracks_names, TRUE,
- _("Merge with..."), _("Select track to merge with"));
+ other_tracks_names,
+ TRUE,
+ _("Merge with..."),
+ track->is_route ? _("Select route to merge with") : _("Select track to merge with"));
g_list_free(other_tracks);
g_list_free(other_tracks_names);
{
GList *l;
for (l = merge_list; l != NULL; l = g_list_next(l)) {
- VikTrack *merge_track = vik_trw_layer_get_track ( vtl, l->data );
+ VikTrack *merge_track;
+ if ( track->is_route )
+ merge_track = vik_trw_layer_get_route ( vtl, l->data );
+ else
+ merge_track = vik_trw_layer_get_track ( vtl, 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, merge_track);
+ if ( track->is_route )
+ vik_trw_layer_delete_route (vtl, merge_track);
+ else
+ vik_trw_layer_delete_track (vtl, merge_track);
track->trackpoints = g_list_sort(track->trackpoints, trackpoint_compare);
}
}
}
/**
- * Join - this allows combining 'routes' and 'tracks'
+ * Join - this allows combining 'tracks' and 'track routes'
* i.e. doesn't care about whether tracks have consistent timestamps
* ATM can only append one track at a time to the currently selected track
*/
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *trk;
+ GHashTable *ght_tracks;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ ght_tracks = vtl->routes;
+ else
+ ght_tracks = vtl->tracks;
+
+ trk = (VikTrack *) g_hash_table_lookup ( ght_tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
GList *other_tracks_names = NULL;
udata.result = &other_tracks_names;
udata.exclude = trk->trackpoints;
- g_hash_table_foreach(vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list_exclude_self, (gpointer)&udata);
+ g_hash_table_foreach(ght_tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list_exclude_self, (gpointer)&udata);
// Note the limit to selecting one track only
// this is to control the ordering of appending tracks, i.e. the selected track always goes after the current track
// (otherwise with multiple select the ordering would not be controllable by the user - automatically being alphabetically)
GList *append_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
- other_tracks_names,
- FALSE,
- _("Append Track"),
- _("Select the track to append after the current track"));
+ other_tracks_names,
+ FALSE,
+ trk->is_route ? _("Append Route"): _("Append Track"),
+ trk->is_route ? _("Select the route to append after the current route") :
+ _("Select the track to append after the current track") );
g_list_free(other_tracks_names);
for (l = append_list; l != NULL; l = g_list_next(l)) {
// TODO: at present this uses the first track found by name,
// which with potential multiple same named tracks may not be the one selected...
- VikTrack *append_track = vik_trw_layer_get_track ( vtl, l->data );
+ VikTrack *append_track;
+ if ( trk->is_route )
+ append_track = vik_trw_layer_get_route ( vtl, l->data );
+ else
+ append_track = vik_trw_layer_get_track ( vtl, l->data );
+
if ( append_track ) {
trk->trackpoints = g_list_concat(trk->trackpoints, append_track->trackpoints);
append_track->trackpoints = NULL;
- vik_trw_layer_delete_track (vtl, append_track);
+ if ( trk->is_route )
+ vik_trw_layer_delete_route (vtl, append_track);
+ else
+ vik_trw_layer_delete_track (vtl, append_track);
+ }
+ }
+ for (l = append_list; l != NULL; l = g_list_next(l))
+ g_free(l->data);
+ g_list_free(append_list);
+ vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+ }
+}
+
+/**
+ * Very similar to trw_layer_append_track for joining
+ * but this allows selection from the 'other' list
+ * If a track is selected, then is shows routes and joins the selected one
+ * If a route is selected, then is shows tracks and joins the selected one
+ */
+static void trw_layer_append_other ( gpointer pass_along[6] )
+{
+
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk;
+ GHashTable *ght_mykind, *ght_others;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
+ ght_mykind = vtl->routes;
+ ght_others = vtl->tracks;
+ }
+ else {
+ ght_mykind = vtl->tracks;
+ ght_others = vtl->routes;
+ }
+
+ trk = (VikTrack *) g_hash_table_lookup ( ght_mykind, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ GList *other_tracks_names = NULL;
+
+ // Sort alphabetically for user presentation
+ // Convert into list of names for usage with dialog function
+ // TODO: Need to consider how to work best when we can have multiple tracks the same name...
+ twt_udata udata;
+ udata.result = &other_tracks_names;
+ udata.exclude = trk->trackpoints;
+
+ g_hash_table_foreach(ght_others, (GHFunc) trw_layer_sorted_track_id_by_name_list_exclude_self, (gpointer)&udata);
+
+ // Note the limit to selecting one track only
+ // this is to control the ordering of appending tracks, i.e. the selected track always goes after the current track
+ // (otherwise with multiple select the ordering would not be controllable by the user - automatically being alphabetically)
+ GList *append_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ other_tracks_names,
+ FALSE,
+ trk->is_route ? _("Append Track"): _("Append Route"),
+ trk->is_route ? _("Select the track to append after the current route") :
+ _("Select the route to append after the current track") );
+
+ g_list_free(other_tracks_names);
+
+ // It's a list, but shouldn't contain more than one other track!
+ if ( append_list ) {
+ GList *l;
+ for (l = append_list; l != NULL; l = g_list_next(l)) {
+ // TODO: at present this uses the first track found by name,
+ // which with potential multiple same named tracks may not be the one selected...
+
+ // Get FROM THE OTHER TYPE list
+ VikTrack *append_track;
+ if ( trk->is_route )
+ append_track = vik_trw_layer_get_track ( vtl, l->data );
+ else
+ append_track = vik_trw_layer_get_route ( vtl, l->data );
+
+ if ( append_track ) {
+
+ if ( !append_track->is_route &&
+ ( ( vik_track_get_segment_count ( append_track ) > 1 ) ||
+ ( vik_track_get_average_speed ( append_track ) > 0.0 ) ) ) {
+
+ if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Converting a track to a route removes extra track data such as segments, timestamps, etc...\nDo you want to continue?"), NULL ) ) {
+ vik_track_merge_segments ( append_track );
+ vik_track_to_routepoints ( append_track );
+ }
+ else {
+ break;
+ }
+ }
+
+ trk->trackpoints = g_list_concat(trk->trackpoints, append_track->trackpoints);
+ append_track->trackpoints = NULL;
+
+ // Delete copied which is FROM THE OTHER TYPE list
+ if ( trk->is_route )
+ vik_trw_layer_delete_track (vtl, append_track);
+ else
+ vik_trw_layer_delete_route (vtl, append_track);
}
}
for (l = append_list; l != NULL; l = g_list_next(l))
/**
* Split a track at the currently selected trackpoint
*/
-static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl )
+static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl, gint subtype )
{
if ( !vtl->current_tpl )
return;
if ( vtl->current_tpl->next && vtl->current_tpl->prev ) {
- gchar *name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, vtl->current_tp_track->name);
+ gchar *name = trw_layer_new_unique_sublayer_name(vtl, subtype, vtl->current_tp_track->name);
if ( name ) {
VikTrack *tr = vik_track_new ();
GList *newglist = g_list_alloc ();
newglist->next = vtl->current_tpl->next;
newglist->data = vik_trackpoint_copy(VIK_TRACKPOINT(vtl->current_tpl->data));
tr->trackpoints = newglist;
+ tr->is_route = vtl->current_tp_track->is_route;
+ tr->visible = TRUE;
vtl->current_tpl->next->prev = newglist; /* end old track here */
vtl->current_tpl->next = NULL;
vtl->current_tpl = newglist; /* change tp to first of new track. */
vtl->current_tp_track = tr;
- tr->visible = TRUE;
-
- vik_trw_layer_add_track ( vtl, name, tr );
+ if ( tr->is_route )
+ vik_trw_layer_add_route ( vtl, name, tr );
+ else
+ vik_trw_layer_add_track ( vtl, name, tr );
trku_udata udata;
udata.trk = tr;
udata.uuid = NULL;
// Also need id of newly created track
- gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+ gpointer *trkf;
+ if ( tr->is_route )
+ trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
+ else
+ trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+
if ( trkf && udata.uuid )
vtl->current_tp_id = udata.uuid;
else
static void trw_layer_split_by_n_points ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *track = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
// Check valid track
GList *trps = track->trackpoints;
tr = vik_track_new();
tr->visible = track->visible;
+ tr->is_route = track->is_route;
tr->trackpoints = (GList *)(iter->data);
- new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, track->name);
- vik_trw_layer_add_track(vtl, new_tr_name, tr);
-
+ if ( track->is_route ) {
+ new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, track->name);
+ vik_trw_layer_add_route(vtl, new_tr_name, tr);
+ }
+ else {
+ new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, track->name);
+ vik_trw_layer_add_track(vtl, new_tr_name, tr);
+ }
iter = g_list_next(iter);
}
// Remove original track and then update the display
- vik_trw_layer_delete_track (vtl, track);
+ if ( track->is_route )
+ vik_trw_layer_delete_route (vtl, track);
+ else
+ vik_trw_layer_delete_track (vtl, track);
vik_layer_emit_update(VIK_LAYER(pass_along[0]), FALSE);
}
g_list_free(newlists);
static void trw_layer_split_at_trackpoint ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- trw_layer_split_at_selected_trackpoint ( vtl );
+ gint subtype = GPOINTER_TO_INT (pass_along[2]);
+ trw_layer_split_at_selected_trackpoint ( vtl, subtype );
}
/**
* Split a track by its segments
+ * Routes do not have segments so don't call this for routes
*/
static void trw_layer_split_segments ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *trk = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *trk = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
guint ntracks;
VikTrack **tracks = vik_track_split_into_segments (trk, &ntracks);
static void trw_layer_delete_points_same_position ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *trk = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *trk;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
gulong removed = vik_track_remove_dup_points ( trk );
static void trw_layer_delete_points_same_time ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *trk = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *trk;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
gulong removed = vik_track_remove_same_time_points ( trk );
static void trw_layer_reverse ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *track = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( ! track )
+ return;
// Check valid track
GList *trps = track->trackpoints;
}
/**
- * Find out if any tracks have the same name in this layer
+ * Find out if any tracks have the same name in this hash table
*/
-static gboolean trw_layer_has_same_track_names ( VikTrwLayer *vtl )
+static gboolean trw_layer_has_same_track_names ( GHashTable *ht_tracks )
{
// Sort items by name, then compare if any next to each other are the same
GList *track_names = NULL;
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+ g_hash_table_foreach ( ht_tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
// No tracks
if ( ! track_names )
}
/**
- * Force unqiue track names for this layer
+ * Force unqiue track names for the track table specified
* Note the panel is a required parameter to enable the update of the names displayed
+ * Specify if on tracks or else on routes
*/
-static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vlp )
+static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vlp, GHashTable *track_table, gboolean ontrack )
{
// . Search list for an instance of repeated name
// . get track of this name
udata.has_same_track_name = FALSE;
udata.same_track_name = NULL;
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+ g_hash_table_foreach ( track_table, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
// No tracks
if ( ! track_names )
while ( udata.has_same_track_name ) {
// Find a track with the same name
- VikTrack *trk = vik_trw_layer_get_track ( vtl, (gpointer) udata.same_track_name );
+ VikTrack *trk;
+ if ( ontrack )
+ trk = vik_trw_layer_get_track ( vtl, (gpointer) udata.same_track_name );
+ else
+ trk = vik_trw_layer_get_route ( vtl, (gpointer) udata.same_track_name );
if ( ! trk ) {
// Broken :(
udataU.uuid = NULL;
// Need want key of it for treeview update
- gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+ gpointer *trkf = g_hash_table_find ( track_table, (GHRFunc) trw_layer_track_find_uuid, &udataU );
if ( trkf && udataU.uuid ) {
- GtkTreeIter *it = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+ GtkTreeIter *it;
+ if ( ontrack )
+ it = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+ else
+ it = g_hash_table_lookup ( vtl->routes_iters, udataU.uuid );
if ( it ) {
vik_treeview_item_set_name ( VIK_LAYER(vtl)->vt, it, newname );
// Start trying to find same names again...
track_names = NULL;
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+ g_hash_table_foreach ( track_table, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
udata.has_same_track_name = FALSE;
GList *dummy_list2 = g_list_sort_with_data ( track_names, check_tracks_for_same_name, &udata );
GList *all = NULL;
// Ensure list of track names offered is unique
- if ( trw_layer_has_same_track_names ( vtl ) ) {
+ if ( trw_layer_has_same_track_names ( vtl->tracks ) ) {
if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
_("Multiple entries with the same name exist. This method only works with unique names. Force unique names now?"), NULL ) ) {
- vik_trw_layer_uniquify_tracks ( vtl, VIK_LAYERS_PANEL(lav[1]) );
+ vik_trw_layer_uniquify_tracks ( vtl, VIK_LAYERS_PANEL(lav[1]), vtl->tracks, TRUE );
}
else
return;
GList *l;
for (l = delete_list; l != NULL; l = g_list_next(l)) {
// This deletes first trk it finds of that name (but uniqueness is enforced above)
- trw_layer_delete_track_by_name (vtl, l->data);
+ trw_layer_delete_track_by_name (vtl, l->data, vtl->tracks);
+ }
+ g_list_free(delete_list);
+ vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+ }
+}
+
+/**
+ *
+ */
+static void trw_layer_delete_routes_from_selection ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ GList *all = NULL;
+
+ // Ensure list of track names offered is unique
+ if ( trw_layer_has_same_track_names ( vtl->routes ) ) {
+ if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Multiple entries with the same name exist. This method only works with unique names. Force unique names now?"), NULL ) ) {
+ vik_trw_layer_uniquify_tracks ( vtl, VIK_LAYERS_PANEL(lav[1]), vtl->routes, FALSE );
+ }
+ else
+ return;
+ }
+
+ // Sort list alphabetically for better presentation
+ g_hash_table_foreach(vtl->routes, (GHFunc) trw_layer_sorted_track_id_by_name_list, &all);
+
+ if ( ! all ) {
+ a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), _("No routes found"));
+ return;
+ }
+
+ // Get list of items to delete from the user
+ GList *delete_list = a_dialog_select_from_list ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ all,
+ TRUE,
+ _("Delete Selection"),
+ _("Select routes to delete") );
+ g_list_free(all);
+
+ // Delete requested routes
+ // since specificly requested, IMHO no need for extra confirmation
+ if ( delete_list ) {
+ GList *l;
+ for (l = delete_list; l != NULL; l = g_list_next(l)) {
+ // This deletes first route it finds of that name (but uniqueness is enforced above)
+ trw_layer_delete_track_by_name (vtl, l->data, vtl->routes);
}
g_list_free(delete_list);
vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
VikWaypoint *wp = g_hash_table_lookup ( l->waypoints, sublayer );
// No actual change to the name supplied
- if (strcmp(newname, wp->name) == 0 )
+ if (strcmp(newname, wp->name) == 0 )
+ return NULL;
+
+ VikWaypoint *wpf = vik_trw_layer_get_waypoint ( l, newname );
+
+ if ( wpf ) {
+ // An existing waypoint has been found with the requested name
+ if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
+ _("A waypoint with the name \"%s\" already exists. Really rename to the same name?"),
+ newname ) )
+ return NULL;
+ }
+
+ // Update WP name and refresh the treeview
+ vik_waypoint_set_name (wp, newname);
+
+#ifdef VIK_CONFIG_ALPHABETIZED_TRW
+ vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, newname );
+#endif
+
+ vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) );
+
+ return newname;
+ }
+
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ {
+ VikTrack *trk = g_hash_table_lookup ( l->tracks, sublayer );
+
+ // No actual change to the name supplied
+ if (strcmp(newname, trk->name) == 0)
return NULL;
- VikWaypoint *wpf = vik_trw_layer_get_waypoint ( l, newname );
+ VikTrack *trkf = vik_trw_layer_get_track ( l, (gpointer) newname );
- if ( wpf ) {
- // An existing waypoint has been found with the requested name
+ if ( trkf ) {
+ // An existing track has been found with the requested name
if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
- _("A waypoint with the name \"%s\" already exists. Really create one with the same name?"),
- newname ) )
+ _("A track with the name \"%s\" already exists. Really rename to the same name?"),
+ newname ) )
return NULL;
}
+ // Update track name and refresh GUI parts
+ vik_track_set_name (trk, newname);
- // Update WP name and refresh the treeview
- vik_waypoint_set_name (wp, newname);
+ // Update any subwindows that could be displaying this track which has changed name
+ // Only one Track Edit Window
+ if ( l->current_tp_track == trk && l->tpwin ) {
+ vik_trw_layer_tpwin_set_track_name ( l->tpwin, newname );
+ }
+ // Property Dialog of the track
+ vik_trw_layer_propwin_update ( trk );
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, newname );
return newname;
}
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE )
{
- VikTrack *trk = g_hash_table_lookup ( l->tracks, sublayer );
+ VikTrack *trk = g_hash_table_lookup ( l->routes, sublayer );
// No actual change to the name supplied
if (strcmp(newname, trk->name) == 0)
return NULL;
- VikTrack *trkf = vik_trw_layer_get_track ( l, (gpointer) newname );
+ VikTrack *trkf = vik_trw_layer_get_route ( l, (gpointer) newname );
if ( trkf ) {
// An existing track has been found with the requested name
if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
- _("A track with the name \"%s\" already exists. Really create one with the same name?"),
+ _("A route with the name \"%s\" already exists. Really rename to the same name?"),
newname ) )
return NULL;
}
a_acquire_set_filter_track ( trk );
}
+#ifdef VIK_CONFIG_GOOGLE
static gboolean is_valid_google_route ( VikTrwLayer *vtl, const gpointer track_id )
{
VikTrack *tr = g_hash_table_lookup ( vtl->tracks, track_id );
g_free ( webpage );
}
}
+#endif
/* vlp can be NULL if necessary - i.e. right-click from a tool */
/* viewpoint is now available instead */
pass_along[6] = iter;
pass_along[7] = NULL; // For misc purposes - maybe track or waypoint
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT || subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT || subtype == VIK_TRW_LAYER_SUBLAYER_TRACK || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE )
{
rv = TRUE;
gtk_widget_show ( item );
if (subtype == VIK_TRW_LAYER_SUBLAYER_TRACK) {
- VikTrwLayer *vtl = l;
- VikTrack *tr = g_hash_table_lookup ( vtl->tracks, sublayer );
+ VikTrack *tr = g_hash_table_lookup ( l->tracks, sublayer );
+ if (tr && tr->property_dialog)
+ gtk_widget_set_sensitive(GTK_WIDGET(item), FALSE );
+ }
+ if (subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE) {
+ VikTrack *tr = g_hash_table_lookup ( l->routes, sublayer );
if (tr && tr->property_dialog)
gtk_widget_set_sensitive(GTK_WIDGET(item), FALSE );
}
}
}
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_TRACKS || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTES ) {
+ item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_PASTE, NULL );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_paste_item_cb), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ // TODO: only enable if suitable item is in clipboard - want to determine *which* sublayer type
+ if ( a_clipboard_type ( ) == VIK_CLIPBOARD_DATA_SUBLAYER )
+ gtk_widget_set_sensitive ( item, TRUE );
+ else
+ gtk_widget_set_sensitive ( item, FALSE );
+
+ // Add separator
+ item = gtk_menu_item_new ();
+ 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) )
{
rv = TRUE;
{
rv = TRUE;
+ if ( l->current_track && !l->current_track->is_route ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Track") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
item = gtk_image_menu_item_new_with_mnemonic ( _("_View All Tracks") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_tracks_view), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_New Track") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(l->current_track) );
+
item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _All Tracks") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_tracks), pass_along );
gtk_widget_show ( item );
}
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTES )
+ {
+ rv = TRUE;
+
+ if ( l->current_track && l->current_track->is_route ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Route") );
+ // Reuse finish track method
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_View All Routes") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_routes_view), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_New Route") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_route), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(l->current_track) );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _All Routes") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_routes), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Delete Routes From Selection...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_routes_from_selection), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
+ GtkWidget *upload_submenu = gtk_menu_new ();
+
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE )
{
item = gtk_menu_item_new ();
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_View Track") );
+ if ( l->current_track && subtype == VIK_TRW_LAYER_SUBLAYER_TRACK && !l->current_track->is_route )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Track") );
+ if ( l->current_track && subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE && l->current_track->is_route )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Route") );
+ if ( l->current_track ) {
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_View Track") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_View Route") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_track_view), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_Maximum Speed") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_MEDIA_FORWARD, GTK_ICON_SIZE_MENU) );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_max_speed), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
- gtk_widget_show ( item );
+ // Routes don't have speeds
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Maximum Speed") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_MEDIA_FORWARD, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_max_speed), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
+ gtk_widget_show ( item );
+ }
GtkWidget *combine_submenu;
combine_submenu = gtk_menu_new ();
gtk_widget_show ( item );
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), combine_submenu );
- item = gtk_menu_item_new_with_mnemonic ( _("_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(combine_submenu), item );
- gtk_widget_show ( item );
+ // Routes don't have times or segments...
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_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(combine_submenu), item );
+ gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Merge _Segments") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_segment), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
+ gtk_widget_show ( item );
+ }
item = gtk_menu_item_new_with_mnemonic ( _("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(combine_submenu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("Merge _Segments") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_segment), pass_along );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Append Track...") );
+ else
+ item = gtk_menu_item_new_with_mnemonic ( _("_Append Route...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_append_track), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("_Append Track...") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_append_track), pass_along );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_menu_item_new_with_mnemonic ( _("Append _Route...") );
+ else
+ item = gtk_menu_item_new_with_mnemonic ( _("Append _Track...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_append_other), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
gtk_widget_show ( item );
gtk_widget_show ( item );
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), split_submenu );
- item = gtk_menu_item_new_with_mnemonic ( _("_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(split_submenu), item );
- gtk_widget_show ( item );
+ // Routes don't have times or segments...
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_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(split_submenu), item );
+ gtk_widget_show ( item );
+
+ // ATM always enable this entry - don't want to have to analyse the track before displaying the menu - to keep the menu speedy
+ item = gtk_menu_item_new_with_mnemonic ( _("Split Se_gments") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_segments), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
+ gtk_widget_show ( item );
+ }
item = gtk_menu_item_new_with_mnemonic ( _("Split By _Number of Points...") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_n_points), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
gtk_widget_show ( item );
- // ATM always enable this entry - don't want to have to analyse the track before displaying the menu - to keep the menu speedy
- item = gtk_menu_item_new_with_mnemonic ( _("Split Se_gments") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_segments), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
- gtk_widget_show ( item );
-
item = gtk_menu_item_new_with_mnemonic ( _("Split at _Trackpoint") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_at_trackpoint), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_Reverse Track") );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Reverse Track") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Reverse Route") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_reverse), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
/* ATM This function is only available via the layers panel, due to the method in finding out the maps in use */
if ( vlp ) {
- item = gtk_image_menu_item_new_with_mnemonic ( _("Down_load Maps Along Track...") );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Down_load Maps Along Track...") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Down_load Maps Along Route...") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Maps Download", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c
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_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("Export Trac_k as GPX...") );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Export Track as GPX...") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Export Route as GPX...") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpx_track), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("E_xtend Track End") );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("E_xtend Track End") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("E_xtend Route End") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
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 );
-#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("C_onvert to a Route") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("C_onvert to a Track") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_CONVERT, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_convert_track_route), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
+#ifdef VIK_CONFIG_GOOGLE
item = gtk_image_menu_item_new_with_mnemonic ( _("Extend _Using Route Finder") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Route Finder", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_route_finder), pass_along );
gtk_widget_show ( item );
#endif
+ // ATM can't upload a single waypoint but can do waypoints to a GPS
+ if ( subtype != VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) {
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Upload") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), upload_submenu );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Upload to GPS...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_gps_upload_any), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(upload_submenu), item );
+ gtk_widget_show ( item );
+ }
+ }
+
+ // Some things aren't usable with routes
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
#ifdef VIK_CONFIG_OPENSTREETMAP
item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
// Convert internal pointer into actual track for usage outside this file
pass_along[7] = g_hash_table_lookup ( l->tracks, sublayer);
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
- gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(upload_submenu), item );
gtk_widget_show ( item );
#endif
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Upload to GPS...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_gps_upload_any), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(upload_submenu), item );
+ gtk_widget_show ( item );
+
+#ifdef VIK_CONFIG_GOOGLE
if ( is_valid_google_route ( l, sublayer ) )
{
item = gtk_image_menu_item_new_with_mnemonic ( _("_View Google Directions") );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
}
+#endif
item = gtk_image_menu_item_new_with_mnemonic ( _("Use with _Filter") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
/* ATM This function is only available via the layers panel, due to needing a vlp */
if ( vlp ) {
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 ) );
+ 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 );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
}
}
#ifdef VIK_CONFIG_GEOTAG
- item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_track), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- gtk_widget_show ( item );
+ item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
#endif
+ }
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
// Only show on viewport popmenu when a trackpoint is selected
if ( ! vlp && l->current_tpl ) {
// Add separator
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
}
-
}
return rv;
/* DOP / sat values remain at defaults as not they do not seem applicable to a dreamt up point */
/* Insert new point into the trackpoints list after the current TP */
- VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
- gint index = g_list_index ( tr->trackpoints, tp_current );
+ VikTrack *trk = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
+ if ( !trk )
+ // Otherwise try routes
+ trk = g_hash_table_lookup ( vtl->routes, vtl->current_tp_id );
+ if ( !trk )
+ return;
+
+ gint index = g_list_index ( trk->trackpoints, tp_current );
if ( index > -1 ) {
- tr->trackpoints = g_list_insert (tr->trackpoints, tp_new, index+1 );
+ trk->trackpoints = g_list_insert ( trk->trackpoints, tp_new, index+1 );
}
}
}
if ( response == VIK_TRW_LAYER_TPWIN_SPLIT && vtl->current_tpl->next && vtl->current_tpl->prev )
{
- trw_layer_split_at_selected_trackpoint ( vtl );
+ trw_layer_split_at_selected_trackpoint ( vtl, vtl->current_tp_track->is_route ? VIK_TRW_LAYER_SUBLAYER_ROUTE : VIK_TRW_LAYER_SUBLAYER_TRACK );
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
}
else if ( response == VIK_TRW_LAYER_TPWIN_DELETE )
{
VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
+ if ( tr == NULL )
+ tr = g_hash_table_lookup ( vtl->routes, vtl->current_tp_id );
if ( tr == NULL )
return;
}
}
+// ATM: Leave this as 'Track' only.
+// Not overly bothered about having a snap to route trackpoint capability
static VikTrackpoint *closest_tp_in_five_pixel_interval ( VikTrwLayer *vtl, VikViewport *vvp, gint x, gint y )
{
TPSearchParams params;
if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
return FALSE;
- if ( !vtl->tracks_visible && !vtl->waypoints_visible )
+ if ( !vtl->tracks_visible && !vtl->waypoints_visible && !vtl->routes_visible )
return FALSE;
// Go for waypoints first as these often will be near a track, but it's likely the wp is wanted rather then the track
}
}
- if (vtl->tracks_visible) {
- TPSearchParams tp_params;
- tp_params.vvp = vvp;
- tp_params.x = event->x;
- tp_params.y = event->y;
- tp_params.closest_track_id = NULL;
- tp_params.closest_tp = NULL;
+ // Used for both track and route lists
+ TPSearchParams tp_params;
+ tp_params.vvp = vvp;
+ tp_params.x = event->x;
+ tp_params.y = event->y;
+ tp_params.closest_track_id = NULL;
+ tp_params.closest_tp = NULL;
+ if (vtl->tracks_visible) {
g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &tp_params);
if ( tp_params.closest_tp ) {
}
}
+ // Try again for routes
+ if (vtl->routes_visible) {
+ g_hash_table_foreach ( vtl->routes, (GHFunc) track_search_closest_tp, &tp_params);
+
+ if ( tp_params.closest_tp ) {
+
+ // Always select + highlight the track
+ vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->routes_iters, tp_params.closest_track_id ), TRUE );
+
+ tet->is_waypoint = FALSE;
+
+ // Select the Trackpoint
+ // Can move it immediately when control held or it's the previously selected tp
+ if ( event->state & GDK_CONTROL_MASK ||
+ vtl->current_tpl == tp_params.closest_tpl ) {
+ // Put into 'move buffer'
+ // NB vvp & vw already set in tet
+ tet->vtl = (gpointer)vtl;
+ marker_begin_move (tet, event->x, event->y);
+ }
+
+ vtl->current_tpl = tp_params.closest_tpl;
+ vtl->current_tp_id = tp_params.closest_track_id;
+ vtl->current_tp_track = g_hash_table_lookup ( vtl->routes, tp_params.closest_track_id );
+
+ set_statusbar_msg_info_trkpt ( vtl, tp_params.closest_tp );
+
+ if ( vtl->tpwin )
+ vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ return TRUE;
+ }
+ }
+
/* these aren't the droids you're looking for */
vtl->current_wp = NULL;
vtl->current_wp_id = NULL;
if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
return FALSE;
- if ( !vtl->tracks_visible && !vtl->waypoints_visible )
+ if ( !vtl->tracks_visible && !vtl->waypoints_visible && !vtl->routes_visible )
return FALSE;
/* Post menu for the currently selected item */
udataU.trk = track;
udataU.uuid = NULL;
- gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+ gpointer *trkf;
+ if ( track->is_route )
+ trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+ else
+ trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU );
if ( trkf && udataU.uuid ) {
- GtkTreeIter *iter = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+ GtkTreeIter *iter;
+ if ( track->is_route )
+ iter = g_hash_table_lookup ( vtl->routes_iters, udataU.uuid );
+ else
+ iter = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
trw_layer_sublayer_add_menu_items ( vtl,
vtl->track_right_click_menu,
NULL,
- VIK_TRW_LAYER_SUBLAYER_TRACK,
+ track->is_route ? VIK_TRW_LAYER_SUBLAYER_ROUTE : VIK_TRW_LAYER_SUBLAYER_TRACK,
udataU.uuid,
iter,
vvp );
g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, ¶ms);
if ( vtl->current_wp == params.closest_wp && vtl->current_wp != NULL )
{
- /* how do we get here? I'm putting in the abort until we can figure it out. -alex */
+ // how do we get here?
marker_begin_move(t, event->x, event->y);
g_critical("shouldn't be here");
- exit(1);
+ return FALSE;
}
else if ( params.closest_wp )
{
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 FALSE;
}
-static const gchar* distance_string (gdouble distance)
+static gchar* distance_string (gdouble distance)
{
gchar str[128];
/* Find out actual distance of current track */
gdouble distance = vik_track_get_length (vtl->current_track);
- const gchar *str = distance_string (distance);
+ gchar *str = distance_string (distance);
statusbar_write (str, elev_gain, elev_loss, vtl);
- g_free ((gpointer)str);
+ g_free (str);
}
/* if we haven't sync'ed yet, we don't have time to do more. */
if ( vtl->draw_sync_done && vtl->current_track && vtl->current_track->trackpoints ) {
GList *iter = g_list_last ( vtl->current_track->trackpoints );
+ VikTrackpoint *last_tpt = VIK_TRACKPOINT(iter->data);
static GdkPixmap *pixmap = NULL;
int w1, h1, w2, h2;
draw_sync_t *passalong;
gint x1, y1;
- vik_viewport_coord_to_screen ( vvp, &(VIK_TRACKPOINT(iter->data)->coord), &x1, &y1 );
+ vik_viewport_coord_to_screen ( vvp, &(last_tpt->coord), &x1, &y1 );
// FOR SCREEN OVERLAYS WE MUST DRAW INTO THIS PIXMAP (when using the reset method)
// otherwise using vik_viewport_draw_* functions puts the data into the base pixmap,
struct LatLon ll;
vik_viewport_screen_to_coord ( vvp, (gint) event->x, (gint) event->y, &coord );
vik_coord_to_latlon ( &coord, &ll );
- distance = distance + vik_coord_diff( &coord, &(VIK_TRACKPOINT(iter->data)->coord));
+ distance = distance + vik_coord_diff( &coord, &(last_tpt->coord));
// Get elevation data
gdouble elev_gain, elev_loss;
gdouble elev_new;
elev_new = (gdouble) a_dems_get_elev_by_coord ( &coord, VIK_DEM_INTERPOL_BEST );
if ( elev_new != VIK_DEM_INVALID_ELEVATION ) {
- if ( VIK_TRACKPOINT(iter->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
+ if ( last_tpt->altitude != VIK_DEFAULT_ALTITUDE ) {
// Adjust elevation of last track point
- if ( elev_new > VIK_TRACKPOINT(iter->data)->altitude )
+ if ( elev_new > last_tpt->altitude )
// Going up
- elev_gain += elev_new - VIK_TRACKPOINT(iter->data)->altitude;
+ elev_gain += elev_new - last_tpt->altitude;
else
// Going down
- elev_loss += VIK_TRACKPOINT(iter->data)->altitude - elev_new;
+ elev_loss += last_tpt->altitude - elev_new;
}
}
- const gchar *str = distance_string (distance);
- gint xd,yd;
- /* offset from cursor a bit */
- xd = event->x + 10;
- yd = event->y - 10;
+ gchar *str = distance_string (distance);
PangoLayout *pl = gtk_widget_create_pango_layout (GTK_WIDGET(vvp), NULL);
- PangoFontDescription *pfd = pango_font_description_from_string ("Sans 8"); // FIXME: settable option? global variable?
- pango_layout_set_font_description (pl, pfd);
- pango_font_description_free (pfd);
+ pango_layout_set_font_description (pl, GTK_WIDGET(vvp)->style->font_desc);
pango_layout_set_text (pl, str, -1);
gint wd, hd;
pango_layout_get_pixel_size ( pl, &wd, &hd );
+ gint xd,yd;
+ // offset from cursor a bit depending on font size
+ xd = event->x + 10;
+ yd = event->y - hd;
+
// Create a background block to make the text easier to read over the background map
GdkGC *background_block_gc = vik_viewport_new_gc ( vvp, "#cccccc", 1);
gdk_draw_rectangle (pixmap, background_block_gc, TRUE, xd-2, yd-2, wd+4, hd+2);
// Update statusbar with full gain/loss information
statusbar_write (str, elev_gain, elev_loss, vtl);
- g_free ((gpointer)str);
+ g_free (str);
// draw pixmap when we have time to
g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, draw_sync, passalong, NULL);
return FALSE;
}
-static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+/*
+ * Common function to handle trackpoint button requests on either a route or a track
+ * . enables adding a point via normal click
+ * . enables removal of last point via right click
+ * . finishing of the track or route via double clicking
+ */
+static gboolean tool_new_track_or_route_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
{
VikTrackpoint *tp;
return FALSE;
}
- if ( event->button == 3 && vtl->current_track )
+ if ( event->button == 3 )
{
+ if ( !vtl->current_track )
+ return FALSE;
/* undo */
if ( vtl->current_track->trackpoints )
{
return TRUE;
}
- if ( ! vtl->current_track )
- {
- gchar *name = trw_layer_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 = vik_trackpoint_new();
vik_viewport_screen_to_coord ( vvp, event->x, event->y, &(tp->coord) );
tp->newsegment = FALSE;
tp->has_timestamp = FALSE;
tp->timestamp = 0;
- vtl->current_track->trackpoints = g_list_append ( vtl->current_track->trackpoints, tp );
- /* Auto attempt to get elevation from DEM data (if it's available) */
- vik_track_apply_dem_data_last_trackpoint ( vtl->current_track );
+
+ if ( vtl->current_track ) {
+ vtl->current_track->trackpoints = g_list_append ( vtl->current_track->trackpoints, tp );
+ /* Auto attempt to get elevation from DEM data (if it's available) */
+ vik_track_apply_dem_data_last_trackpoint ( vtl->current_track );
+ }
vtl->ct_x1 = vtl->ct_x2;
vtl->ct_y1 = vtl->ct_y2;
return TRUE;
}
+static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+ // ----------------------------------------------------- if current is a route - switch to new track
+ if ( event->button == 1 && ( ! vtl->current_track || (vtl->current_track && vtl->current_track->is_route ) ))
+ {
+ gchar *name = trw_layer_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, FALSE ) ) )
+ {
+ vtl->current_track = vik_track_new();
+ vtl->current_track->visible = TRUE;
+ vik_trw_layer_add_track ( vtl, name, vtl->current_track );
+ }
+ else
+ return TRUE;
+ }
+ return tool_new_track_or_route_click ( vtl, event, vvp );
+}
+
static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
{
if ( event->button == 2 ) {
}
}
+/*** New route ****/
+
+static gpointer tool_new_route_create ( VikWindow *vw, VikViewport *vvp)
+{
+ return vvp;
+}
+
+static gboolean tool_new_route_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+ // -------------------------- if current is a track - switch to new route
+ if ( event->button == 1 && ( ! vtl->current_track || (vtl->current_track && !vtl->current_track->is_route ) ) )
+ {
+ gchar *name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, _("Route"));
+ if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->routes, name, TRUE ) ) )
+ {
+ vtl->current_track = vik_track_new();
+ vtl->current_track->visible = TRUE;
+ vtl->current_track->is_route = TRUE;
+ vik_trw_layer_add_route ( vtl, name, vtl->current_track );
+ }
+ else
+ return TRUE;
+ }
+ return tool_new_track_or_route_click ( vtl, event, vvp );
+}
+
/*** New waypoint ****/
static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp)
if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
return FALSE;
- if ( !vtl->vl.visible || !vtl->tracks_visible )
+ if ( !vtl->vl.visible || !vtl->tracks_visible || !vtl->routes_visible )
return FALSE;
if ( vtl->current_tpl )
}
- g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, ¶ms);
+ if ( vtl->tracks_visible )
+ g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, ¶ms);
if ( params.closest_tp )
{
return TRUE;
}
+ if ( vtl->routes_visible )
+ g_hash_table_foreach ( vtl->routes, (GHFunc) track_search_closest_tp, ¶ms);
+
+ if ( params.closest_tp )
+ {
+ vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->routes_iters, params.closest_track_id ), TRUE );
+ vtl->current_tpl = params.closest_tpl;
+ vtl->current_tp_id = params.closest_track_id;
+ vtl->current_tp_track = g_hash_table_lookup ( vtl->routes, params.closest_track_id );
+ trw_layer_tpwin_init ( vtl );
+ set_statusbar_msg_info_trkpt ( vtl, params.closest_tp );
+ vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ return TRUE;
+ }
+
/* these aren't the droids you're looking for */
return FALSE;
}
}
-#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+#ifdef VIK_CONFIG_GOOGLE
/*** Route Finder ***/
static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp)
{
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 );
+ a_babel_convert_from_url ( vtl, url, "google", NULL, NULL );
g_free ( url );
/* see if anything was done -- a track was added or appended to */
gboolean vik_trw_layer_uniquify ( VikTrwLayer *vtl, VikLayersPanel *vlp )
{
if ( vtl && vlp ) {
- vik_trw_layer_uniquify_tracks ( vtl, vlp );
+ vik_trw_layer_uniquify_tracks ( vtl, vlp, vtl->tracks, TRUE );
+ vik_trw_layer_uniquify_tracks ( vtl, vlp, vtl->routes, FALSE );
vik_trw_layer_uniquify_waypoints ( vtl, vlp );
return TRUE;
}
}
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);
+ maps_layer_download_section (vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level);
}
if (fillins) {
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] );
+ VikTrack *trk;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ if ( !trk )
+ return;
+
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, TRUE); // Includes hidden map layer types
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]);
+ vik_track_download_map(trk, map_layers[selected_map], vvp, zoom_vals[selected_zoom]);
done:
for (i = 0; i < num_maps; i++)