]> git.street.me.uk Git - andy/viking.git/blob - src/vikwebtool_datasource.c
[DOC] Fix some incorrect docbook markup.
[andy/viking.git] / src / vikwebtool_datasource.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4  *
5  * Copyright (C) 2013, Rob Norris <rw_norris@hotmail.com>
6  *
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.
11  *
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.
16  *
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
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "vikwebtool_datasource.h"
28
29 #include <string.h>
30
31 #include <glib.h>
32 #include <glib/gi18n.h>
33
34 #include "globals.h"
35 #include "acquire.h"
36 #include "util.h"
37
38 static GObjectClass *parent_class;
39
40 static void webtool_datasource_finalize ( GObject *gob );
41
42 static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw );
43
44 typedef struct _VikWebtoolDatasourcePrivate VikWebtoolDatasourcePrivate;
45
46 struct _VikWebtoolDatasourcePrivate
47 {
48         gchar *url;
49         gchar *url_format_code;
50         gchar *file_type;
51 };
52
53 #define WEBTOOL_DATASOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
54                                            VIK_WEBTOOL_DATASOURCE_TYPE,      \
55                                            VikWebtoolDatasourcePrivate))
56
57 G_DEFINE_TYPE (VikWebtoolDatasource, vik_webtool_datasource, VIK_WEBTOOL_TYPE)
58
59 enum
60 {
61         PROP_0,
62         PROP_URL,
63         PROP_URL_FORMAT_CODE,
64         PROP_FILE_TYPE,
65 };
66
67 static void webtool_datasource_set_property (GObject      *object,
68                                              guint         property_id,
69                                              const GValue *value,
70                                              GParamSpec   *pspec)
71 {
72         VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
73         VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
74
75         switch ( property_id ) {
76         case PROP_URL:
77                 g_free ( priv->url );
78                 priv->url = g_value_dup_string ( value );
79                 g_debug ( "VikWebtoolDatasource.url: %s", priv->url );
80                 break;
81
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 );
86                 break;
87
88         case PROP_FILE_TYPE:
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 );
92                 break;
93
94         default:
95                 /* We don't have any other property... */
96                 G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
97                 break;
98     }
99 }
100
101 static void webtool_datasource_get_property (GObject    *object,
102                                              guint       property_id,
103                                              GValue     *value,
104                                              GParamSpec *pspec)
105 {
106         VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
107         VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
108
109         switch ( property_id ) {
110
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;
114
115         default:
116                 /* We don't have any other property... */
117                 G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
118                 break;
119     }
120 }
121
122 typedef struct {
123         VikExtTool *self;
124         VikWindow *vw;
125         VikViewport *vvp;
126 } datasource_t;
127
128 static gpointer datasource_init ( acq_vik_t *avt )
129 {
130         datasource_t *data = g_malloc(sizeof(*data));
131         data->self = avt->userdata;
132         data->vw = avt->vw;
133         data->vvp = avt->vvp;
134         return data;
135 }
136
137 static void datasource_get_cmd_string ( gpointer user_data, gchar **cmd, gchar **extra, DownloadMapOptions *options )
138 {
139         datasource_t *data = (datasource_t*) user_data;
140
141         VikWebtool *vwd = VIK_WEBTOOL ( data->self );
142         gchar *url = vik_webtool_get_url ( vwd, data->vw );
143         g_debug ("%s: %s", __FUNCTION__, url );
144
145         *cmd = g_strdup ( url );
146
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);
155         if ( parts )
156                 *extra = g_strdup ( parts[0] );
157         else
158                 *extra = NULL;
159         g_strfreev ( parts );
160
161         options = NULL;
162 }
163
164 static gboolean datasource_process ( VikTrwLayer *vtl, const gchar *cmd, const gchar *extra, BabelStatusFunc status_cb, acq_dialog_widgets_t *adw, DownloadMapOptions *options )
165 {
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);
170         return result;
171 }
172
173 static void cleanup ( gpointer data )
174 {
175         g_free ( data );
176 }
177
178 static void webtool_datasource_open ( VikExtTool *self, VikWindow *vw )
179 {
180         // Use VikDataSourceInterface to give thready goodness controls of downloading stuff (i.e. can cancel the request)
181
182         // Can now create a 'VikDataSourceInterface' on the fly...
183         VikDataSourceInterface *vik_datasource_interface = g_malloc(sizeof(VikDataSourceInterface));
184
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
192                 TRUE,
193                 TRUE,
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,
203                 NULL,
204                 0,
205                 NULL,
206                 NULL,
207                 0
208         };
209         memcpy ( vik_datasource_interface, &data, sizeof(VikDataSourceInterface) );
210
211         a_acquire ( vw, vik_window_layers_panel(vw), vik_window_viewport (vw), vik_datasource_interface, self, cleanup );
212 }
213
214 static void vik_webtool_datasource_class_init ( VikWebtoolDatasourceClass *klass )
215 {
216         GObjectClass *gobject_class;
217         VikWebtoolClass *base_class;
218         GParamSpec *pspec;
219
220         gobject_class = G_OBJECT_CLASS (klass);
221
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;
225
226         pspec = g_param_spec_string ("url",
227                                      "Template 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,
232                                          PROP_URL,
233                                          pspec);
234
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,
242                                          pspec);
243
244         pspec = g_param_spec_string ("file_type",
245                                      "The file type expected",
246                                      "Set the file type",
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,
250                                          PROP_FILE_TYPE,
251                                          pspec);
252
253         parent_class = g_type_class_peek_parent (klass);
254
255         base_class = VIK_WEBTOOL_CLASS ( klass );
256         base_class->get_url = webtool_datasource_get_url;
257
258         // Override default open function here:
259         VikExtToolClass *ext_tool_class = VIK_EXT_TOOL_CLASS ( klass );
260         ext_tool_class->open = webtool_datasource_open;
261
262         g_type_class_add_private (klass, sizeof (VikWebtoolDatasourcePrivate));
263 }
264
265 VikWebtoolDatasource *vik_webtool_datasource_new ()
266 {
267         return VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE, NULL ) );
268 }
269
270 VikWebtoolDatasource *vik_webtool_datasource_new_with_members ( const gchar *label,
271                                                                 const gchar *url,
272                                                                 const gchar *url_format_code,
273                                                                 const gchar *file_type )
274 {
275         VikWebtoolDatasource *result = VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE,
276                                                                 "label", label,
277                                                                 "url", url,
278                                                                 "url_format_code", url_format_code,
279                                                                 "file_type", file_type,
280                                                                 NULL ) );
281
282         return result;
283 }
284
285 static void vik_webtool_datasource_init ( VikWebtoolDatasource *self )
286 {
287         VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE (self);
288         priv->url = NULL;
289         priv->url_format_code = NULL;
290         priv->file_type = NULL;
291 }
292
293 static void webtool_datasource_finalize ( GObject *gob )
294 {
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);
300 }
301
302 #define MAX_NUMBER_CODES 7
303
304 /**
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
307  */
308 static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw )
309 {
310         VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
311         VikViewport *viewport = vik_window_viewport ( vw );
312
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 );
320
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);
327
328         // Center values
329         const VikCoord *coord = vik_viewport_get_center ( viewport );
330         struct LatLon ll;
331         vik_coord_to_latlon ( coord, &ll );
332
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);
337
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 ) );
342
343         gchar szoom[G_ASCII_DTOSTR_BUF_SIZE];
344         g_snprintf ( szoom, G_ASCII_DTOSTR_BUF_SIZE, "%d", zoom );
345
346         gint len = 0;
347         if ( priv->url_format_code )
348                 len = strlen ( priv->url_format_code );
349         if ( len > MAX_NUMBER_CODES )
350                 len = MAX_NUMBER_CODES;
351
352         gchar* values[MAX_NUMBER_CODES];
353         int i;
354         for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
355                 values[i] = g_strdup ( "" );
356         }
357
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;
367                 default: break;
368                 }
369         }
370
371         gchar *url = g_strdup_printf ( priv->url, values[0], values[1], values[2], values[3], values[4], values[5], values[6] );
372
373         for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
374                 g_free ( values[i] );
375         }
376         
377         return url;
378 }