]> git.street.me.uk Git - andy/viking.git/blob - src/datasource_gps.c
Enable control of create_label_vbox spacing and padding.
[andy/viking.git] / src / datasource_gps.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5  * Copyright (C) 2006, Alex Foobarian <foobarian@gmail.com>
6  * Copyright (C) 2012, Rob Norris <rw_norris@hotmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <string.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 #include <glib/gstdio.h>
32 #include <glib/gprintf.h>
33 #include <glib/gi18n.h>
34
35 #include "datasource_gps.h"
36 #include "viking.h"
37 #include "babel.h"
38 #include "gpx.h"
39 #include "acquire.h"
40
41 static gboolean gps_acquire_in_progress = FALSE;
42
43 static gint last_active = -1;
44
45 static gpointer datasource_gps_init_func ( acq_vik_t *avt );
46 static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file, gpointer not_used );
47 static void datasource_gps_cleanup ( gpointer user_data );
48 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
49 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
50 static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
51 static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
52
53 VikDataSourceInterface vik_datasource_gps_interface = {
54   N_("Acquire from GPS"),
55   N_("Acquired from GPS"),
56   VIK_DATASOURCE_CREATENEWLAYER,
57   VIK_DATASOURCE_INPUTTYPE_NONE,
58   TRUE,
59   TRUE,
60   TRUE,
61   (VikDataSourceInitFunc)               datasource_gps_init_func,
62   (VikDataSourceCheckExistenceFunc)     NULL,
63   (VikDataSourceAddSetupWidgetsFunc)    datasource_gps_add_setup_widgets,
64   (VikDataSourceGetCmdStringFunc)       datasource_gps_get_cmd_string,
65   (VikDataSourceProcessFunc)        a_babel_convert_from,
66   (VikDataSourceProgressFunc)           datasource_gps_progress,
67   (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
68   (VikDataSourceCleanupFunc)            datasource_gps_cleanup,
69   (VikDataSourceOffFunc)                datasource_gps_off
70 };
71
72 /*********************************************************
73  * Definitions and routines for acquiring data from GPS
74  *********************************************************/
75
76 /* widgets in setup dialog specific to GPS */
77 /* widgets in progress dialog specific to GPS */
78 /* also counts needed for progress */
79 typedef struct {
80   /* setup dialog */
81   GtkWidget *proto_l;
82   GtkWidget *proto_b;
83   GtkWidget *ser_l;
84   GtkWidget *ser_b;
85   GtkWidget *off_request_l;
86   GtkCheckButton *off_request_b;
87   GtkWidget *get_tracks_l;
88   GtkCheckButton *get_tracks_b;
89   GtkWidget *get_routes_l;
90   GtkCheckButton *get_routes_b;
91   GtkWidget *get_waypoints_l;
92   GtkCheckButton *get_waypoints_b;
93
94   /* progress dialog */
95   GtkWidget *gps_label;
96   GtkWidget *ver_label;
97   GtkWidget *id_label;
98   GtkWidget *wp_label;
99   GtkWidget *trk_label;
100   GtkWidget *rte_label;
101   GtkWidget *progress_label;
102   vik_gps_xfer_type progress_type;
103
104   /* state */
105   int total_count;
106   int count;
107   // Know which way xfer is so xfer setting types are only stored for download
108   vik_gps_dir direction;
109 } gps_user_data_t;
110
111 #define VIK_SETTINGS_GPS_GET_TRACKS "gps_download_tracks"
112 #define VIK_SETTINGS_GPS_GET_ROUTES "gps_download_routes"
113 #define VIK_SETTINGS_GPS_GET_WAYPOINTS "gps_download_waypoints"
114 #define VIK_SETTINGS_GPS_PROTOCOL "gps_protocol"
115 #define VIK_SETTINGS_GPS_PORT "gps_port"
116 #define VIK_SETTINGS_GPS_POWER_OFF "gps_power_off"
117
118 static gpointer datasource_gps_init_func ( acq_vik_t *avt )
119 {
120   gps_user_data_t *gps_ud = g_malloc (sizeof(gps_user_data_t));
121   gps_ud->direction = GPS_DOWN;
122   return gps_ud;
123 }
124
125 /**
126  * datasource_gps_get_protocol:
127  *
128  * Method to get the communication protocol of the GPS device from the widget structure
129  */
130 gchar* datasource_gps_get_protocol ( gpointer user_data )
131 {
132   // Uses the list of supported devices
133   gps_user_data_t *w = (gps_user_data_t *)user_data;
134   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
135   if (a_babel_device_list) {
136     gchar *protocol = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
137     a_settings_set_string ( VIK_SETTINGS_GPS_PROTOCOL, protocol );
138     return protocol;
139   }
140
141   return NULL;
142 }
143
144 /**
145  * datasource_gps_get_descriptor:
146  *
147  * Method to get the descriptor from the widget structure
148  * "Everything is a file"
149  * Could actually be normal file or a serial port
150  */
151 gchar* datasource_gps_get_descriptor ( gpointer user_data )
152 {
153   gps_user_data_t *w = (gps_user_data_t *)user_data;
154
155 #if GTK_CHECK_VERSION (2, 24, 0)
156   gchar *descriptor = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w->ser_b));
157 #else
158   gchar *descriptor = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
159 #endif
160   a_settings_set_string ( VIK_SETTINGS_GPS_PORT, descriptor );
161   return descriptor;
162 }
163
164 /**
165  * datasource_gps_get_do_tracks:
166  *
167  * Method to get the track handling behaviour from the widget structure
168  */
169 gboolean datasource_gps_get_do_tracks ( gpointer user_data )
170 {
171   gps_user_data_t *w = (gps_user_data_t *)user_data;
172   gboolean get_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_tracks_b));
173   if ( w->direction == GPS_DOWN )
174     a_settings_set_boolean ( VIK_SETTINGS_GPS_GET_TRACKS, get_tracks );
175   return get_tracks;
176 }
177
178 /**
179  * datasource_gps_get_do_routes:
180  *
181  * Method to get the route handling behaviour from the widget structure
182  */
183 gboolean datasource_gps_get_do_routes ( gpointer user_data )
184 {
185   gps_user_data_t *w = (gps_user_data_t *)user_data;
186   gboolean get_routes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_routes_b));
187   if ( w->direction == GPS_DOWN )
188     a_settings_set_boolean ( VIK_SETTINGS_GPS_GET_ROUTES, get_routes );
189   return get_routes;
190 }
191
192 /**
193  * datasource_gps_get_do_waypoints:
194  *
195  * Method to get the waypoint handling behaviour from the widget structure
196  */
197 gboolean datasource_gps_get_do_waypoints ( gpointer user_data )
198 {
199   gps_user_data_t *w = (gps_user_data_t *)user_data;
200   gboolean get_waypoints = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b));
201   if ( w->direction == GPS_DOWN )
202     a_settings_set_boolean ( VIK_SETTINGS_GPS_GET_WAYPOINTS, get_waypoints );
203   return get_waypoints;
204 }
205
206 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file, gpointer not_used )
207 {
208   char *device = NULL;
209   char *tracks = NULL;
210   char *routes = NULL;
211   char *waypoints = NULL;
212
213   if (gps_acquire_in_progress) {
214     *babelargs = *input_file = NULL;
215   }
216   
217   gps_acquire_in_progress = TRUE;
218
219   device = datasource_gps_get_protocol ( user_data );
220
221   if ( datasource_gps_get_do_tracks ( user_data ) )
222     tracks = "-t";
223   else
224     tracks = "";
225
226   if ( datasource_gps_get_do_routes ( user_data ) )
227     routes = "-r";
228   else
229     routes = "";
230
231   if ( datasource_gps_get_do_waypoints ( user_data ) )
232     waypoints = "-w";
233   else
234     waypoints = "";
235
236   *babelargs = g_strdup_printf("-D 9 %s %s %s -i %s", tracks, routes, waypoints, device);
237   /* device points to static content => no free */
238   device = NULL;
239   tracks = NULL;
240   routes = NULL;
241   waypoints = NULL;
242
243   *input_file = g_strdup(datasource_gps_get_descriptor(user_data));
244
245   g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
246 }
247
248 /**
249  * datasource_gps_get_off:
250  *
251  * Method to get the off behaviour from the widget structure
252  */
253 gboolean datasource_gps_get_off ( gpointer user_data )
254 {
255   gps_user_data_t *w = (gps_user_data_t *)user_data;
256   gboolean power_off = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b));
257   a_settings_set_boolean ( VIK_SETTINGS_GPS_POWER_OFF, power_off );
258   return power_off;
259 }
260
261 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
262 {
263   char *ser = NULL;
264   char *device = NULL;
265   gps_user_data_t *w = (gps_user_data_t *)user_data;
266
267   if (gps_acquire_in_progress) {
268     *babelargs = *input_file = NULL;
269   }
270
271   /* See if we should turn off the device */
272   if (!datasource_gps_get_off ( user_data )){
273     return;
274   }
275   
276   if (!a_babel_device_list)
277     return;
278   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
279   device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
280   if (!strcmp(device, "garmin")) {
281     device = "garmin,power_off";
282   }
283   else if (!strcmp(device, "navilink")) {
284     device = "navilink,power_off";
285   }
286   else {
287     return;
288   }
289
290   *babelargs = g_strdup_printf("-i %s", device);
291   /* device points to static content => no free */
292   device = NULL;
293   
294 #if GTK_CHECK_VERSION (2, 24, 0)
295   ser = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w->ser_b));
296 #else
297   ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
298 #endif
299   *input_file = g_strdup(ser);
300 }
301
302
303 static void datasource_gps_cleanup ( gpointer user_data )
304 {
305   g_free ( user_data );
306   gps_acquire_in_progress = FALSE;
307 }
308
309 /**
310  * datasource_gps_clean_up:
311  *
312  * External method to tidy up
313  */
314 void datasource_gps_clean_up ( gpointer user_data )
315 {
316   datasource_gps_cleanup ( user_data );
317 }
318
319 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
320 {
321   gchar *s = NULL;
322   gdk_threads_enter();
323   if (w->running) {
324     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
325     const gchar *tmp_str;
326     switch (gps_data->progress_type) {
327     case WPT: tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt); gps_data->total_count = cnt; break;
328     case TRK: tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt); gps_data->total_count = cnt; break;
329     default:
330       {
331         // Maybe a gpsbabel bug/feature (upto at least v1.4.3 or maybe my Garmin device) but the count always seems x2 too many for routepoints
332         gint mycnt = (cnt / 2) + 1;
333         tmp_str = ngettext("Downloading %d routepoint...", "Downloading %d routepoints...", mycnt);
334         gps_data->total_count = mycnt;
335         break;
336       }
337     }
338     s = g_strdup_printf(tmp_str, cnt);
339     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
340     gtk_widget_show ( gps_data->progress_label );
341   }
342   g_free(s); s = NULL;
343   gdk_threads_leave();
344 }
345
346 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
347 {
348   gchar *s = NULL;
349   gdk_threads_enter();
350   if (w->running) {
351     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
352
353     if (cnt < gps_data->total_count) {
354       switch (gps_data->progress_type) {
355       case WPT: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "waypoints"); break;
356       case TRK: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "trackpoints"); break;
357       default: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "routepoints"); break;
358       }
359     } else {
360       switch (gps_data->progress_type) {
361       case WPT: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "waypoints"); break;
362       case TRK: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "trackpoints"); break;
363       default: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "routepoints"); break;
364       }
365     }
366     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
367   }
368   g_free(s); s = NULL;
369   gdk_threads_leave();
370 }
371
372 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
373 {
374   gchar *s = NULL;
375   gdk_threads_enter();
376   if (w->running) {
377     s = g_strdup_printf(_("GPS Device: %s"), info);
378     gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
379   }
380   g_free(s); s = NULL;
381   gdk_threads_leave();
382 }
383
384 /* 
385  * This routine relies on gpsbabel's diagnostic output to display the progress information. 
386  * These outputs differ when different GPS devices are used, so we will need to test
387  * them on several and add the corresponding support.
388  */
389 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
390 {
391   gchar *line;
392   gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
393
394   switch(c) {
395   case BABEL_DIAG_OUTPUT:
396     line = (gchar *)data;
397
398     gdk_threads_enter();
399     if (w->running) {
400       gtk_label_set_text ( GTK_LABEL(w->status), _("Status: Working...") );
401     }
402     gdk_threads_leave();
403
404     /* tells us the type of items that will follow */
405     if (strstr(line, "Xfer Wpt")) {
406       gps_data->progress_label = gps_data->wp_label;
407       gps_data->progress_type = WPT;
408     }
409     if (strstr(line, "Xfer Trk")) {
410       gps_data->progress_label = gps_data->trk_label;
411       gps_data->progress_type = TRK;
412     }
413     if (strstr(line, "Xfer Rte")) {
414       gps_data->progress_label = gps_data->rte_label;
415       gps_data->progress_type = RTE;
416     }
417
418     if (strstr(line, "PRDDAT")) {
419       gchar **tokens = g_strsplit(line, " ", 0);
420       gchar info[128];
421       int ilen = 0;
422       int i;
423       int n_tokens = 0;
424
425       while (tokens[n_tokens])
426         n_tokens++;
427
428       if (n_tokens > 8) {
429         for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
430           guint ch;
431           sscanf(tokens[i], "%x", &ch);
432           info[ilen++] = ch;
433         }
434         info[ilen++] = 0;
435         set_gps_info(info, w);
436       }
437       g_strfreev(tokens);
438     }
439     /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
440     if (strstr(line, "Unit:")) {
441       gchar **tokens = g_strsplit(line, "\t", 0);
442       int n_tokens = 0;
443       while (tokens[n_tokens])
444         n_tokens++;
445
446       if (n_tokens > 1) {
447         set_gps_info(tokens[1], w);
448       }
449       g_strfreev(tokens);
450     }
451     /* tells us how many items there will be */
452     if (strstr(line, "RECORD")) {
453       int lsb, msb, cnt;
454
455       if (strlen(line) > 20) {
456        sscanf(line+17, "%x", &lsb); 
457        sscanf(line+20, "%x", &msb);
458        cnt = lsb + msb * 256;
459        set_total_count(cnt, w);
460        gps_data->count = 0;
461       }
462     }
463     if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") || strstr(line, "RTEHDR") || strstr(line, "RTEWPT") ) {
464       gps_data->count++;
465       set_current_count(gps_data->count, w);
466     }
467     break;
468   case BABEL_DONE:
469     break;
470   default:
471     break;
472   }
473 }
474
475 void append_element (gpointer elem, gpointer user_data)
476 {
477   const gchar *text = ((BabelDevice*)elem)->label;
478   vik_combo_box_text_append (GTK_WIDGET(user_data), text);
479 }
480
481 static gint find_entry = -1;
482 static gint garmin_entry = -1;
483 static gint wanted_entry = -1;
484
485 static void find_protocol (gpointer elem, gpointer user_data)
486 {
487   const gchar *name = ((BabelDevice*)elem)->name;
488   const gchar *protocol = user_data;
489   find_entry++;
490   if (!strcmp(name, protocol)) {
491     wanted_entry = find_entry;
492   }
493 }
494
495 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
496 {
497   gps_user_data_t *w = (gps_user_data_t *)user_data;
498   GtkTable *box, *data_type_box;
499
500   w->proto_l = gtk_label_new (_("GPS Protocol:"));
501   w->proto_b = vik_combo_box_text_new ();
502   g_list_foreach (a_babel_device_list, append_element, w->proto_b);
503
504   if ( last_active < 0 ) {
505     find_entry = -1;
506     wanted_entry = -1;
507     gchar *protocol = NULL;
508     if ( a_settings_get_string ( VIK_SETTINGS_GPS_PROTOCOL, &protocol ) ) {
509       // Use setting
510       if ( protocol )
511         g_list_foreach (a_babel_device_list, find_protocol, protocol);
512       // If not found set it to the first entry, otherwise use the entry
513       last_active = ( wanted_entry < 0 ) ? 0 : wanted_entry;
514     }
515     else {
516       // Maintain default to Garmin devices (assumed most popular/numerous device)
517       garmin_entry = -1;
518       g_list_foreach (a_babel_device_list, find_protocol, "garmin");
519       last_active = ( garmin_entry < 0 ) ? 0 : garmin_entry;
520     }
521   }
522
523   gtk_combo_box_set_active (GTK_COMBO_BOX(w->proto_b), last_active);
524   g_object_ref(w->proto_b);
525
526   w->ser_l = gtk_label_new (_("Serial Port:"));
527 #if GTK_CHECK_VERSION (2, 24, 0)
528   w->ser_b = gtk_combo_box_text_new_with_entry ();
529 #else
530   w->ser_b = gtk_combo_box_entry_new_text ();
531 #endif
532   // Value from the settings is promoted to the top
533   gchar *gps_port = NULL;
534   if ( a_settings_get_string ( VIK_SETTINGS_GPS_PORT, &gps_port ) ) {
535     // Use setting if available
536     if ( gps_port ) {
537 #ifndef WINDOWS
538       if ( !strncmp (gps_port, "/dev/tty", 6) ) {
539         if (g_access (gps_port, R_OK) == 0) {
540           vik_combo_box_text_append (w->ser_b, gps_port);
541         }
542       }
543       else
544 #endif
545         vik_combo_box_text_append (w->ser_b, gps_port);
546     }
547   }
548
549   // Note avoid appending the port selected from the settings
550 #ifdef WINDOWS
551   if ( gps_port && strcmp (gps_port, "com1") )
552     vik_combo_box_text_append (w->ser_b, "com1");
553 #else
554   /* Here just try to see if the device is available which gets passed onto gpsbabel
555      List USB devices first as these will generally only be present if autogenerated by udev or similar
556      User is still able to set their own free text entry */
557   if ( gps_port && strcmp (gps_port, "/dev/ttyUSB0") )
558     if (g_access ("/dev/ttyUSB0", R_OK) == 0)
559       vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB0");
560   if ( gps_port && strcmp (gps_port, "/dev/ttyUSB1") )
561     if (g_access ("/dev/ttyUSB1", R_OK) == 0)
562       vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB1");
563   if ( gps_port && strcmp (gps_port, "/dev/ttyS0") )
564     if (g_access ("/dev/ttyS0", R_OK) == 0)
565       vik_combo_box_text_append (w->ser_b, "/dev/ttyS0");
566   if ( gps_port && strcmp (gps_port, "/dev/ttyS1") )
567     if (g_access ("/dev/ttyS1", R_OK) == 0)
568       vik_combo_box_text_append (w->ser_b, "/dev/ttyS1");
569 #endif
570   if ( gps_port && strcmp (gps_port, "usb:") )
571     vik_combo_box_text_append (w->ser_b, "usb:");
572
573   gtk_combo_box_set_active (GTK_COMBO_BOX(w->ser_b), 0);
574   g_object_ref(w->ser_b);
575
576   w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
577   w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
578   gboolean power_off;
579   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_POWER_OFF, &power_off ) )
580     power_off = FALSE;
581   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->off_request_b), power_off);
582
583   w->get_tracks_l = gtk_label_new (_("Tracks:"));
584   w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
585   gboolean get_tracks;
586   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_TRACKS, &get_tracks ) )
587     get_tracks = TRUE;
588   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_tracks_b), get_tracks);
589
590   w->get_routes_l = gtk_label_new (_("Routes:"));
591   w->get_routes_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
592   gboolean get_routes;
593   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_ROUTES, &get_routes ) )
594     get_routes = FALSE;
595   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_routes_b), get_routes);
596
597   w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
598   w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
599   gboolean get_waypoints;
600   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_WAYPOINTS, &get_waypoints ) )
601     get_waypoints = TRUE;
602   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b), get_waypoints);
603
604   box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
605   data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
606
607   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
608   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
609   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
610   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
611   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_l), 0, 1, 0, 1);
612   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_b), 1, 2, 0, 1);
613   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_l), 2, 3, 0, 1);
614   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_b), 3, 4, 0, 1);
615   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_l), 4, 5, 0, 1);
616   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_b), 5, 6, 0, 1);
617   gtk_table_attach_defaults(box, GTK_WIDGET(data_type_box), 0, 2, 2, 3);
618   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 3, 4);
619   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 3, 4);
620   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 );
621
622   gtk_widget_show_all ( dialog );
623 }
624
625 /**
626  * datasource_gps_setup:
627  * @dialog: The GTK dialog. The caller is responsible for managing the dialog creation/deletion
628  * @xfer: The default type of items enabled for transfer, others disabled.
629  * @xfer_all: When specified all items are enabled for transfer.
630  *
631  * Returns: A gpointer to the private structure for GPS progress/information widgets
632  *          Pass this pointer back into the other exposed datasource_gps_X functions
633  */
634 gpointer datasource_gps_setup ( GtkWidget *dialog, vik_gps_xfer_type xfer, gboolean xfer_all )
635 {
636   gps_user_data_t *w_gps = (gps_user_data_t *)datasource_gps_init_func ( NULL );
637   w_gps->direction = GPS_UP;
638   datasource_gps_add_setup_widgets ( dialog, NULL, w_gps );
639
640   gboolean way = xfer_all;
641   gboolean trk = xfer_all;
642   gboolean rte = xfer_all;
643
644   // Selectively turn bits on
645   if ( !xfer_all ) {
646     switch (xfer) {
647     case WPT: way = TRUE; break;
648     case RTE: rte = TRUE; break;
649     default: trk = TRUE; break;
650     }
651   }
652
653   // Apply
654   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_tracks_b), trk );
655   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_l), trk );
656   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_b), trk );
657
658   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_routes_b), rte );
659   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_l), rte );
660   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_b), rte );
661
662   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_waypoints_b), way );
663   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_l), way );
664   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_b), way );
665
666   return (gpointer)w_gps;
667 }
668
669 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
670 {
671   GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel, *rtelabel;
672
673   gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
674
675   gpslabel = gtk_label_new (_("GPS device: N/A"));
676   verlabel = gtk_label_new ("");
677   idlabel = gtk_label_new ("");
678   wplabel = gtk_label_new ("");
679   trklabel = gtk_label_new ("");
680   rtelabel = gtk_label_new ("");
681
682   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), gpslabel, FALSE, FALSE, 5 );
683   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), wplabel, FALSE, FALSE, 5 );
684   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), trklabel, FALSE, FALSE, 5 );
685   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), rtelabel, FALSE, FALSE, 5 );
686
687   gtk_widget_show_all ( dialog );
688
689   w_gps->gps_label = gpslabel;
690   w_gps->id_label = idlabel;
691   w_gps->ver_label = verlabel;
692   w_gps->progress_label = w_gps->wp_label = wplabel;
693   w_gps->trk_label = trklabel;
694   w_gps->rte_label = rtelabel;
695   w_gps->total_count = -1;
696 }