1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
5 * Copyright (C) 2013, Rob Norris <rw_norris@hotmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "vikwebtool_datasource.h"
32 #include <glib/gi18n.h>
38 static GObjectClass *parent_class;
40 static void webtool_datasource_finalize ( GObject *gob );
42 static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw );
44 typedef struct _VikWebtoolDatasourcePrivate VikWebtoolDatasourcePrivate;
46 struct _VikWebtoolDatasourcePrivate
49 gchar *url_format_code;
53 #define WEBTOOL_DATASOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
54 VIK_WEBTOOL_DATASOURCE_TYPE, \
55 VikWebtoolDatasourcePrivate))
57 G_DEFINE_TYPE (VikWebtoolDatasource, vik_webtool_datasource, VIK_WEBTOOL_TYPE)
67 static void webtool_datasource_set_property (GObject *object,
72 VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
73 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
75 switch ( property_id ) {
78 priv->url = g_value_dup_string ( value );
79 g_debug ( "VikWebtoolDatasource.url: %s", priv->url );
82 case PROP_URL_FORMAT_CODE:
83 g_free ( priv->url_format_code );
84 priv->url_format_code = g_value_dup_string ( value );
85 g_debug ( "VikWebtoolDatasource.url_format_code: %s", priv->url_format_code );
89 g_free ( priv->file_type );
90 priv->file_type = g_value_dup_string ( value );
91 g_debug ( "VikWebtoolDatasource.file_type: %s", priv->url_format_code );
95 /* We don't have any other property... */
96 G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
101 static void webtool_datasource_get_property (GObject *object,
106 VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
107 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
109 switch ( property_id ) {
111 case PROP_URL: g_value_set_string ( value, priv->url ); break;
112 case PROP_URL_FORMAT_CODE: g_value_set_string ( value, priv->url_format_code ); break;
113 case PROP_FILE_TYPE: g_value_set_string ( value, priv->url ); break;
116 /* We don't have any other property... */
117 G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
128 static gpointer datasource_init ( acq_vik_t *avt )
130 datasource_t *data = g_malloc(sizeof(*data));
131 data->self = avt->userdata;
133 data->vvp = avt->vvp;
137 static void datasource_get_cmd_string ( gpointer user_data, gchar **cmd, gchar **extra, DownloadMapOptions *options )
139 datasource_t *data = (datasource_t*) user_data;
141 VikWebtool *vwd = VIK_WEBTOOL ( data->self );
142 gchar *url = vik_webtool_get_url ( vwd, data->vw );
143 g_debug ("%s: %s", __FUNCTION__, url );
145 *cmd = g_strdup ( url );
147 // Only use first section of the file_type string
148 // One can't use values like 'kml -x transform,rte=wpt' in order to do fancy things
149 // since it won't be in the right order for the overall GPSBabel command
150 // So prevent any potentially dangerous behaviour
151 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( data->self );
152 gchar **parts = NULL;
153 if ( priv->file_type )
154 parts = g_strsplit ( priv->file_type, " ", 0);
156 *extra = g_strdup ( parts[0] );
159 g_strfreev ( parts );
164 static gboolean datasource_process ( VikTrwLayer *vtl, const gchar *cmd, const gchar *extra, BabelStatusFunc status_cb, acq_dialog_widgets_t *adw, DownloadMapOptions *options )
166 //datasource_t *data = (datasource_t *)adw->user_data;
167 // Dependent on the ExtTool / what extra has been set to...
168 // When extra is NULL - then it interprets results as a GPX
169 gboolean result = a_babel_convert_from_url ( vtl, cmd, extra, status_cb, adw, options);
173 static void cleanup ( gpointer data )
178 static void webtool_datasource_open ( VikExtTool *self, VikWindow *vw )
180 // Use VikDataSourceInterface to give thready goodness controls of downloading stuff (i.e. can cancel the request)
182 // Can now create a 'VikDataSourceInterface' on the fly...
183 VikDataSourceInterface *vik_datasource_interface = g_malloc(sizeof(VikDataSourceInterface));
185 // An 'easy' way of assigning values
186 VikDataSourceInterface data = {
187 vik_ext_tool_get_label (self),
188 vik_ext_tool_get_label (self),
189 VIK_DATASOURCE_ADDTOLAYER,
190 VIK_DATASOURCE_INPUTTYPE_NONE,
191 FALSE, // Maintain current view - rather than setting it to the acquired points
194 (VikDataSourceInitFunc) datasource_init,
195 (VikDataSourceCheckExistenceFunc) NULL,
196 (VikDataSourceAddSetupWidgetsFunc) NULL,
197 (VikDataSourceGetCmdStringFunc) datasource_get_cmd_string,
198 (VikDataSourceProcessFunc) datasource_process,
199 (VikDataSourceProgressFunc) NULL,
200 (VikDataSourceAddProgressWidgetsFunc) NULL,
201 (VikDataSourceCleanupFunc) cleanup,
202 (VikDataSourceOffFunc) NULL,
209 memcpy ( vik_datasource_interface, &data, sizeof(VikDataSourceInterface) );
211 a_acquire ( vw, vik_window_layers_panel(vw), vik_window_viewport (vw), vik_datasource_interface, self, cleanup );
214 static void vik_webtool_datasource_class_init ( VikWebtoolDatasourceClass *klass )
216 GObjectClass *gobject_class;
217 VikWebtoolClass *base_class;
220 gobject_class = G_OBJECT_CLASS (klass);
222 gobject_class->finalize = webtool_datasource_finalize;
223 gobject_class->set_property = webtool_datasource_set_property;
224 gobject_class->get_property = webtool_datasource_get_property;
226 pspec = g_param_spec_string ("url",
228 "Set the template URL",
229 VIKING_URL /* default value */,
230 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
231 g_object_class_install_property (gobject_class,
235 pspec = g_param_spec_string ("url_format_code",
236 "Template URL Format Code",
237 "Set the template URL format code",
238 "LRBT", // default value
239 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
240 g_object_class_install_property (gobject_class,
241 PROP_URL_FORMAT_CODE,
244 pspec = g_param_spec_string ("file_type",
245 "The file type expected",
247 NULL, // default value ~ equates to internal GPX reading
248 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
249 g_object_class_install_property (gobject_class,
253 parent_class = g_type_class_peek_parent (klass);
255 base_class = VIK_WEBTOOL_CLASS ( klass );
256 base_class->get_url = webtool_datasource_get_url;
258 // Override default open function here:
259 VikExtToolClass *ext_tool_class = VIK_EXT_TOOL_CLASS ( klass );
260 ext_tool_class->open = webtool_datasource_open;
262 g_type_class_add_private (klass, sizeof (VikWebtoolDatasourcePrivate));
265 VikWebtoolDatasource *vik_webtool_datasource_new ()
267 return VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE, NULL ) );
270 VikWebtoolDatasource *vik_webtool_datasource_new_with_members ( const gchar *label,
272 const gchar *url_format_code,
273 const gchar *file_type )
275 VikWebtoolDatasource *result = VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE,
278 "url_format_code", url_format_code,
279 "file_type", file_type,
285 static void vik_webtool_datasource_init ( VikWebtoolDatasource *self )
287 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE (self);
289 priv->url_format_code = NULL;
290 priv->file_type = NULL;
293 static void webtool_datasource_finalize ( GObject *gob )
295 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( gob );
296 g_free ( priv->url ); priv->url = NULL;
297 g_free ( priv->url_format_code ); priv->url_format_code = NULL;
298 g_free ( priv->file_type ); priv->file_type = NULL;
299 G_OBJECT_CLASS(parent_class)->finalize(gob);
302 #define MAX_NUMBER_CODES 7
305 * Calculate individual elements (similarly to the VikWebtool Bounds & Center) for *all* potential values
306 * Then only values specified by the URL format are used in parameterizing the URL
308 static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw )
310 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
311 VikViewport *viewport = vik_window_viewport ( vw );
313 // Get top left and bottom right lat/lon pairs from the viewport
314 gdouble min_lat, max_lat, min_lon, max_lon;
315 gchar sminlon[G_ASCII_DTOSTR_BUF_SIZE];
316 gchar smaxlon[G_ASCII_DTOSTR_BUF_SIZE];
317 gchar sminlat[G_ASCII_DTOSTR_BUF_SIZE];
318 gchar smaxlat[G_ASCII_DTOSTR_BUF_SIZE];
319 vik_viewport_get_min_max_lat_lon ( viewport, &min_lat, &max_lat, &min_lon, &max_lon );
321 // Cannot simply use g_strdup_printf and gdouble due to locale.
322 // As we compute an URL, we have to think in C locale.
323 g_ascii_dtostr (sminlon, G_ASCII_DTOSTR_BUF_SIZE, min_lon);
324 g_ascii_dtostr (smaxlon, G_ASCII_DTOSTR_BUF_SIZE, max_lon);
325 g_ascii_dtostr (sminlat, G_ASCII_DTOSTR_BUF_SIZE, min_lat);
326 g_ascii_dtostr (smaxlat, G_ASCII_DTOSTR_BUF_SIZE, max_lat);
329 const VikCoord *coord = vik_viewport_get_center ( viewport );
331 vik_coord_to_latlon ( coord, &ll );
333 gchar scenterlat[G_ASCII_DTOSTR_BUF_SIZE];
334 gchar scenterlon[G_ASCII_DTOSTR_BUF_SIZE];
335 g_ascii_dtostr (scenterlat, G_ASCII_DTOSTR_BUF_SIZE, ll.lat);
336 g_ascii_dtostr (scenterlon, G_ASCII_DTOSTR_BUF_SIZE, ll.lon);
338 guint8 zoom = 17; // A zoomed in default
339 // zoom - ideally x & y factors need to be the same otherwise use the default
340 if ( vik_viewport_get_xmpp ( viewport ) == vik_viewport_get_ympp ( viewport ) )
341 zoom = mpp_to_zoom ( vik_viewport_get_zoom ( viewport ) );
343 gchar szoom[G_ASCII_DTOSTR_BUF_SIZE];
344 g_snprintf ( szoom, G_ASCII_DTOSTR_BUF_SIZE, "%d", zoom );
347 if ( priv->url_format_code )
348 len = strlen ( priv->url_format_code );
349 if ( len > MAX_NUMBER_CODES )
350 len = MAX_NUMBER_CODES;
352 gchar* values[MAX_NUMBER_CODES];
354 for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
355 values[i] = g_strdup ( "" );
358 for ( i = 0; i < len; i++ ) {
359 switch ( g_ascii_toupper ( priv->url_format_code[i] ) ) {
360 case 'L': values[i] = g_strdup ( sminlon ); break;
361 case 'R': values[i] = g_strdup ( smaxlon ); break;
362 case 'B': values[i] = g_strdup ( sminlat ); break;
363 case 'T': values[i] = g_strdup ( smaxlat ); break;
364 case 'A': values[i] = g_strdup ( scenterlat ); break;
365 case 'O': values[i] = g_strdup ( scenterlon ); break;
366 case 'Z': values[i] = g_strdup ( szoom ); break;
371 gchar *url = g_strdup_printf ( priv->url, values[0], values[1], values[2], values[3], values[4], values[5], values[6] );
373 for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
374 g_free ( values[i] );