From: Rob Norris Date: Fri, 27 Mar 2015 23:47:49 +0000 (+0000) Subject: Enable invoking Web Tools via right click menus on selected layers or points. X-Git-Url: https://git.street.me.uk/andy/viking.git/commitdiff_plain/027ff770382cd253209596b94deaa3ebcfe26841 Enable invoking Web Tools via right click menus on selected layers or points. Extend Web Tools to accept a coordinate parameter, so that it can use that location in forming the URL. --- diff --git a/help/C/viking.xml b/help/C/viking.xml index a5fef066..fa4ae26f 100644 --- a/help/C/viking.xml +++ b/help/C/viking.xml @@ -3281,7 +3281,7 @@ Accept: */* url - the parametrized URL to open in the spirit of C printf format, with up to 7 "%s" values. e.g. http://hostname/getfile?lat=%s&lon=%s + the parametrized URL to open in the spirit of C printf format, with up to 9 "%s" values. e.g. http://hostname/getfile?lat=%s&lon=%s The order and meaning of these parameters is given by the url_format_code below @@ -3296,6 +3296,8 @@ Accept: */* A = center lAtitude of the current view O = center lOngitude of the current view Z = OSM Zoom value of the current view. See Zoom Levels + P = selected Point's latitude + N = selected poiNt's longitude S = A user specified input string requested from the user via a dialog box Thus for the url example above then the format code should be AO diff --git a/src/vikexttool.c b/src/vikexttool.c index 0b735bd3..d76dcc86 100644 --- a/src/vikexttool.c +++ b/src/vikexttool.c @@ -177,3 +177,9 @@ void vik_ext_tool_open ( VikExtTool *self, VikWindow *vwindow ) { VIK_EXT_TOOL_GET_CLASS( self )->open( self, vwindow ); } + +void vik_ext_tool_open_at_position ( VikExtTool *self, VikWindow *vwindow, VikCoord *vc ) +{ + if ( VIK_EXT_TOOL_GET_CLASS( self )->open_at_position ) + VIK_EXT_TOOL_GET_CLASS( self )->open_at_position( self, vwindow, vc ); +} diff --git a/src/vikexttool.h b/src/vikexttool.h index 8f396816..14e625cd 100644 --- a/src/vikexttool.h +++ b/src/vikexttool.h @@ -24,6 +24,7 @@ #include #include "vikwindow.h" +#include "vikcoord.h" G_BEGIN_DECLS @@ -43,6 +44,7 @@ struct _VikExtToolClass GObjectClass object_class; gchar *(* get_label) (VikExtTool *self); void (* open) (VikExtTool *self, VikWindow *vwindow); + void (* open_at_position) (VikExtTool *self, VikWindow *vwindow, VikCoord *vc); }; GType vik_ext_tool_get_type (); @@ -53,6 +55,7 @@ struct _VikExtTool { gchar *vik_ext_tool_get_label ( VikExtTool *self ); void vik_ext_tool_open ( VikExtTool *self, VikWindow *vwindow ); +void vik_ext_tool_open_at_position ( VikExtTool *self, VikWindow *vwindow, VikCoord *vc ); G_END_DECLS diff --git a/src/vikexttools.c b/src/vikexttools.c index 7ae540f5..d504a50a 100644 --- a/src/vikexttools.c +++ b/src/vikexttools.c @@ -30,6 +30,7 @@ #include #define VIK_TOOL_DATA_KEY "vik-tool-data" +#define VIK_TOOL_WIN_KEY "vik-tool-win" static GList *ext_tools_list = NULL; @@ -79,3 +80,40 @@ void vik_ext_tools_add_action_items ( VikWindow *vwindow, GtkUIManager *uim, Gtk } } } + +static void ext_tool_open_at_position_cb ( GtkWidget *widget, VikCoord *vc ) +{ + gpointer ptr = g_object_get_data ( G_OBJECT(widget), VIK_TOOL_DATA_KEY ); + VikExtTool *ext_tool = VIK_EXT_TOOL ( ptr ); + gpointer wptr = g_object_get_data ( G_OBJECT(widget), VIK_TOOL_WIN_KEY ); + VikWindow *vw = VIK_WINDOW ( wptr ); + vik_ext_tool_open_at_position ( ext_tool, vw, vc ); +} + +/** + * Add to any menu + * mostly for allowing to assign for TrackWaypoint layer menus + */ +void vik_ext_tools_add_menu_items_to_menu ( VikWindow *vw, GtkMenu *menu, VikCoord *vc ) +{ + for (GList *iter = ext_tools_list; iter; iter = iter->next) { + VikExtTool *ext_tool = NULL; + gchar *label = NULL; + ext_tool = VIK_EXT_TOOL ( iter->data ); + label = vik_ext_tool_get_label ( ext_tool ); + if ( label ) { + GtkWidget *item = NULL; + item = gtk_menu_item_new_with_label ( _(label) ); + g_free ( label ); label = NULL; + // Store some data into the menu entry + g_object_set_data ( G_OBJECT(item), VIK_TOOL_DATA_KEY, ext_tool ); + g_object_set_data ( G_OBJECT(item), VIK_TOOL_WIN_KEY, vw ); + if ( vc ) + g_signal_connect ( G_OBJECT(item), "activate", G_CALLBACK(ext_tool_open_at_position_cb), vc ); + else + g_signal_connect ( G_OBJECT(item), "activate", G_CALLBACK(ext_tools_open_cb), vw ); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show ( item ); + } + } +} diff --git a/src/vikexttools.h b/src/vikexttools.h index 35fac628..c7671464 100644 --- a/src/vikexttools.h +++ b/src/vikexttools.h @@ -32,6 +32,7 @@ G_BEGIN_DECLS void vik_ext_tools_register ( VikExtTool *tool ); void vik_ext_tools_unregister_all (); void vik_ext_tools_add_action_items ( VikWindow *vwindow, GtkUIManager *uim, GtkActionGroup *action_group, guint mid ); +void vik_ext_tools_add_menu_items_to_menu ( VikWindow *vw, GtkMenu *menu, VikCoord *vc ); G_END_DECLS diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 38bdf004..2de4ada3 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -59,6 +59,7 @@ #include "acquire.h" #include "datasources.h" #include "datasource_gps.h" +#include "vikexttools.h" #include "vikexttool_datasources.h" #include "ui_util.h" #include "vikutils.h" @@ -4025,6 +4026,17 @@ void trw_layer_osm_traces_upload_track_cb ( menu_array_sublayer values ) } } +static GtkWidget* create_external_submenu ( GtkMenu *menu ) +{ + GtkWidget *external_submenu = gtk_menu_new (); + GtkWidget *item = gtk_image_menu_item_new_with_mnemonic ( _("Externa_l") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_EXECUTE, 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), external_submenu ); + return external_submenu; +} + static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vlp ) { static menu_array_layer pass_along; @@ -4350,6 +4362,10 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); gtk_widget_set_sensitive ( item, (gboolean)(g_hash_table_size (vtl->waypoints)) ); + + GtkWidget *external_submenu = create_external_submenu ( menu ); + // TODO: Should use selected layer's centre - rather than implicitly using the current viewport + vik_ext_tools_add_menu_items_to_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), GTK_MENU (external_submenu), NULL ); } // Fake Waypoint UUIDs vi simple increasing integer @@ -8532,22 +8548,18 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men } } - // Only made available if a suitable program is installed + GtkWidget *external_submenu = create_external_submenu ( menu ); + + // These are only made available if a suitable program is installed if ( (have_astro_program || have_diary_program) && (subtype == VIK_TRW_LAYER_SUBLAYER_TRACK || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) ) { - GtkWidget *external_submenu; - external_submenu = gtk_menu_new (); - item = gtk_image_menu_item_new_with_mnemonic ( _("Externa_l") ); - gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_EXECUTE, 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), external_submenu ); if ( have_diary_program ) { item = gtk_image_menu_item_new_with_mnemonic ( _("_Diary") ); gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_SPELL_CHECK, GTK_ICON_SIZE_MENU) ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_diary), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(external_submenu), item ); + gtk_widget_set_tooltip_text (item, _("Open diary program at this date")); gtk_widget_show ( item ); } @@ -8555,10 +8567,27 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men item = gtk_image_menu_item_new_with_mnemonic ( _("_Astronomy") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_astro), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(external_submenu), item ); + gtk_widget_set_tooltip_text (item, _("Open astronomy program at this date and location")); gtk_widget_show ( item ); } } + if ( l->current_tpl || l->current_wp ) { + // For the selected point + VikCoord *vc; + if ( l->current_tpl ) + vc = &(VIK_TRACKPOINT(l->current_tpl->data)->coord); + else + vc = &(l->current_wp->coord); + vik_ext_tools_add_menu_items_to_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(l)), GTK_MENU (external_submenu), vc ); + } + else { + // Otherwise for the selected sublayer + // TODO: Should use selected items centre - rather than implicitly using the current viewport + vik_ext_tools_add_menu_items_to_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(l)), GTK_MENU (external_submenu), NULL ); + } + + #ifdef VIK_CONFIG_GOOGLE if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE && is_valid_google_route ( l, sublayer ) ) { diff --git a/src/vikwebtool.c b/src/vikwebtool.c index 3210be1e..8ceff421 100644 --- a/src/vikwebtool.c +++ b/src/vikwebtool.c @@ -36,6 +36,7 @@ static GObjectClass *parent_class; static void webtool_finalize ( GObject *gob ); static void webtool_open ( VikExtTool *self, VikWindow *vwindow ); +static void webtool_open_at_position ( VikExtTool *self, VikWindow *vwindow, VikCoord *vc ); G_DEFINE_ABSTRACT_TYPE (VikWebtool, vik_webtool, VIK_EXT_TOOL_TYPE) @@ -52,6 +53,7 @@ static void vik_webtool_class_init ( VikWebtoolClass *klass ) ext_tool_class = VIK_EXT_TOOL_CLASS ( klass ); ext_tool_class->open = webtool_open; + ext_tool_class->open_at_position = webtool_open_at_position; } VikWebtool *vik_webtool_new () @@ -78,7 +80,25 @@ static void webtool_open ( VikExtTool *self, VikWindow *vwindow ) g_free ( url ); } +static void webtool_open_at_position ( VikExtTool *self, VikWindow *vwindow, VikCoord *vc ) +{ + VikWebtool *vwd = VIK_WEBTOOL ( self ); + gchar *url = vik_webtool_get_url_at_position ( vwd, vwindow, vc ); + if ( url ) { + open_url ( GTK_WINDOW(vwindow), url ); + g_free ( url ); + } +} + gchar *vik_webtool_get_url ( VikWebtool *self, VikWindow *vwindow ) { return VIK_WEBTOOL_GET_CLASS( self )->get_url( self, vwindow ); } + +gchar *vik_webtool_get_url_at_position ( VikWebtool *self, VikWindow *vwindow, VikCoord *vc ) +{ + if ( VIK_WEBTOOL_GET_CLASS( self )->get_url_at_position ) + return VIK_WEBTOOL_GET_CLASS( self )->get_url_at_position( self, vwindow, vc ); + else + return NULL; +} diff --git a/src/vikwebtool.h b/src/vikwebtool.h index 0ed6ae30..80df7f5f 100644 --- a/src/vikwebtool.h +++ b/src/vikwebtool.h @@ -44,6 +44,7 @@ struct _VikWebtoolClass { VikExtToolClass object_class; gchar *(* get_url) (VikWebtool *self, VikWindow *vwindow); + gchar *(* get_url_at_position) (VikWebtool *self, VikWindow *vwindow, VikCoord *vc); }; GType vik_webtool_get_type (); @@ -53,6 +54,7 @@ struct _VikWebtool { }; gchar *vik_webtool_get_url ( VikWebtool *self, VikWindow *vwindow ); +gchar *vik_webtool_get_url_at_position ( VikWebtool *self, VikWindow *vwindow, VikCoord *vc ); G_END_DECLS diff --git a/src/vikwebtoolbounds.c b/src/vikwebtoolbounds.c index b95162c9..c2d733da 100644 --- a/src/vikwebtoolbounds.c +++ b/src/vikwebtoolbounds.c @@ -2,7 +2,7 @@ /* * viking -- GPS Data and Topo Analyzer, Explorer, and Manager * - * Copyright (C) 2011, Rob Norris + * Copyright (C) 2011-2015, Rob Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,8 +36,8 @@ static GObjectClass *parent_class; static void webtool_bounds_finalize ( GObject *gob ); - static gchar *webtool_bounds_get_url ( VikWebtool *vw, VikWindow *vwindow ); +static gchar *webtool_bounds_get_url_at_position ( VikWebtool *vw, VikWindow *vwindow, VikCoord *vc ); typedef struct _VikWebtoolBoundsPrivate VikWebtoolBoundsPrivate; @@ -131,8 +131,7 @@ vik_webtool_bounds_class_init ( VikWebtoolBoundsClass *klass ) base_class = VIK_WEBTOOL_CLASS ( klass ); base_class->get_url = webtool_bounds_get_url; - - //klass->mpp_to_zoom = webtool_bounds_mpp_to_zoom; + base_class->get_url_at_position = webtool_bounds_get_url_at_position; g_type_class_add_private (klass, sizeof (VikWebtoolBoundsPrivate)); } @@ -191,3 +190,10 @@ static gchar *webtool_bounds_get_url ( VikWebtool *self, VikWindow *vwindow ) return g_strdup_printf ( priv->url, sminlon, smaxlon, sminlat, smaxlat ); } + +static gchar *webtool_bounds_get_url_at_position ( VikWebtool *self, VikWindow *vwindow, VikCoord *vc ) +{ + // TODO: could use zoom level to generate an offset from center lat/lon to get the bounds + // For now simply use the existing function to use bounds from the viewport + return webtool_bounds_get_url ( self, vwindow ); +} diff --git a/src/vikwebtoolcenter.c b/src/vikwebtoolcenter.c index 3cef2ba4..3ef83ed5 100644 --- a/src/vikwebtoolcenter.c +++ b/src/vikwebtoolcenter.c @@ -40,6 +40,7 @@ static void webtool_center_finalize ( GObject *gob ); static guint8 webtool_center_mpp_to_zoom ( VikWebtool *self, gdouble mpp ); static gchar *webtool_center_get_url ( VikWebtool *vw, VikWindow *vwindow ); +static gchar *webtool_center_get_url_at_position ( VikWebtool *vw, VikWindow *vwindow, VikCoord *vc ); typedef struct _VikWebtoolCenterPrivate VikWebtoolCenterPrivate; @@ -133,6 +134,7 @@ vik_webtool_center_class_init ( VikWebtoolCenterClass *klass ) base_class = VIK_WEBTOOL_CLASS ( klass ); base_class->get_url = webtool_center_get_url; + base_class->get_url_at_position = webtool_center_get_url_at_position; klass->mpp_to_zoom = webtool_center_mpp_to_zoom; @@ -172,21 +174,25 @@ static guint8 webtool_center_mpp_to_zoom ( VikWebtool *self, gdouble mpp ) { return map_utils_mpp_to_zoom_level ( mpp ); } -static gchar *webtool_center_get_url ( VikWebtool *self, VikWindow *vwindow ) +static gchar *webtool_center_get_url_at_position ( VikWebtool *self, VikWindow *vwindow, VikCoord *vc ) { VikWebtoolCenterPrivate *priv = NULL; VikViewport *viewport = NULL; - const VikCoord *coord = NULL; guint8 zoom = 17; struct LatLon ll; gchar strlat[G_ASCII_DTOSTR_BUF_SIZE], strlon[G_ASCII_DTOSTR_BUF_SIZE]; priv = WEBTOOL_CENTER_GET_PRIVATE (self); viewport = vik_window_viewport ( vwindow ); - // Coords - coord = vik_viewport_get_center ( viewport ); - vik_coord_to_latlon ( coord, &ll ); + // Use the provided position otherwise use center of the viewport + if ( vc ) + vik_coord_to_latlon ( vc, &ll ); + else { + const VikCoord *coord = NULL; + coord = vik_viewport_get_center ( viewport ); + vik_coord_to_latlon ( coord, &ll ); + } // zoom - ideally x & y factors need to be the same otherwise use the default if ( vik_viewport_get_xmpp ( viewport ) == vik_viewport_get_ympp ( viewport ) ) @@ -200,6 +206,11 @@ static gchar *webtool_center_get_url ( VikWebtool *self, VikWindow *vwindow ) return g_strdup_printf ( priv->url, strlat, strlon, zoom ); } +static gchar *webtool_center_get_url ( VikWebtool *self, VikWindow *vwindow ) +{ + return webtool_center_get_url_at_position ( self, vwindow, NULL ); +} + guint8 vik_webtool_center_mpp_to_zoom (VikWebtool *self, gdouble mpp) { return VIK_WEBTOOL_CENTER_GET_CLASS( self )->mpp_to_zoom( self, mpp ); diff --git a/src/vikwebtoolformat.c b/src/vikwebtoolformat.c index 9cc41327..d8612f0e 100644 --- a/src/vikwebtoolformat.c +++ b/src/vikwebtoolformat.c @@ -39,6 +39,7 @@ static void webtool_format_finalize ( GObject *gob ); static guint8 webtool_format_mpp_to_zoom ( VikWebtool *self, gdouble mpp ); static gchar *webtool_format_get_url ( VikWebtool *vw, VikWindow *vwindow ); +static gchar *webtool_format_get_url_at_position ( VikWebtool *vw, VikWindow *vwindow, VikCoord *vc ); typedef struct _VikWebtoolFormatPrivate VikWebtoolFormatPrivate; @@ -150,6 +151,7 @@ vik_webtool_format_class_init ( VikWebtoolFormatClass *klass ) base_class = VIK_WEBTOOL_CLASS ( klass ); base_class->get_url = webtool_format_get_url; + base_class->get_url_at_position = webtool_format_get_url_at_position; klass->mpp_to_zoom = webtool_format_mpp_to_zoom; @@ -194,9 +196,9 @@ static guint8 webtool_format_mpp_to_zoom ( VikWebtool *self, gdouble mpp ) { return map_utils_mpp_to_zoom_level ( mpp ); } -#define MAX_NUMBER_CODES 7 +#define MAX_NUMBER_CODES 9 -static gchar *webtool_format_get_url ( VikWebtool *self, VikWindow *vw ) +static gchar *webtool_format_get_url_at_position ( VikWebtool *self, VikWindow *vw, VikCoord *vc ) { VikWebtoolFormatPrivate *priv = NULL; priv = WEBTOOL_FORMAT_GET_PRIVATE (self); @@ -228,6 +230,16 @@ static gchar *webtool_format_get_url ( VikWebtool *self, VikWindow *vw ) g_ascii_dtostr (scenterlat, G_ASCII_DTOSTR_BUF_SIZE, ll.lat); g_ascii_dtostr (scenterlon, G_ASCII_DTOSTR_BUF_SIZE, ll.lon); + struct LatLon llpt; + llpt.lat = 0.0; + llpt.lon = 0.0; + if ( vc ) + vik_coord_to_latlon ( vc, &ll ); + gchar spointlat[G_ASCII_DTOSTR_BUF_SIZE]; + gchar spointlon[G_ASCII_DTOSTR_BUF_SIZE]; + g_ascii_dtostr (spointlat, G_ASCII_DTOSTR_BUF_SIZE, llpt.lat); + g_ascii_dtostr (spointlon, G_ASCII_DTOSTR_BUF_SIZE, llpt.lon); + guint8 zoom = 17; // A zoomed in default // zoom - ideally x & y factors need to be the same otherwise use the default if ( vik_viewport_get_xmpp ( viewport ) == vik_viewport_get_ympp ( viewport ) ) @@ -257,11 +269,13 @@ static gchar *webtool_format_get_url ( VikWebtool *self, VikWindow *vw ) case 'A': values[i] = g_strdup ( scenterlat ); break; case 'O': values[i] = g_strdup ( scenterlon ); break; case 'Z': values[i] = g_strdup ( szoom ); break; + case 'P': values[i] = g_strdup ( spointlat ); break; + case 'N': values[i] = g_strdup ( spointlon ); break; default: break; } } - gchar *url = g_strdup_printf ( priv->url, values[0], values[1], values[2], values[3], values[4], values[5], values[6] ); + gchar *url = g_strdup_printf ( priv->url, values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8] ); for ( i = 0; i < MAX_NUMBER_CODES; i++ ) { if ( values[i] != '\0' ) @@ -272,6 +286,11 @@ static gchar *webtool_format_get_url ( VikWebtool *self, VikWindow *vw ) return url; } +static gchar *webtool_format_get_url ( VikWebtool *self, VikWindow *vw ) +{ + return webtool_format_get_url_at_position ( self, vw, NULL ); +} + guint8 vik_webtool_format_mpp_to_zoom (VikWebtool *self, gdouble mpp) { return VIK_WEBTOOL_FORMAT_GET_CLASS( self )->mpp_to_zoom( self, mpp );