]> git.street.me.uk Git - andy/viking.git/blob - src/dialog.c
Initial revision
[andy/viking.git] / src / dialog.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "viking.h"
23 #include "thumbnails.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28
29 void a_dialog_msg ( GtkWindow *parent, gint type, const gchar *info, const gchar *extra )
30 {
31   GtkWidget *msgbox = gtk_message_dialog_new ( parent, GTK_DIALOG_DESTROY_WITH_PARENT, type, GTK_BUTTONS_OK, info, extra );
32   gtk_dialog_run ( GTK_DIALOG(msgbox) );
33   gtk_widget_destroy ( msgbox );
34 }
35
36 gboolean a_dialog_goto_latlon ( GtkWindow *parent, struct LatLon *ll, const struct LatLon *old )
37 {
38   GtkWidget *dialog = gtk_dialog_new_with_buttons ("Go to Lat/Lon",
39                                                   parent,
40                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
41                                                   GTK_STOCK_CANCEL,
42                                                   GTK_RESPONSE_REJECT,
43                                                   GTK_STOCK_OK,
44                                                   GTK_RESPONSE_ACCEPT,
45                                                   NULL);
46   GtkWidget *latlabel, *lonlabel;
47   GtkWidget *lat, *lon;
48   gchar *tmp_lat, *tmp_lon;
49
50   latlabel = gtk_label_new ("Latitude:");
51   lat = gtk_entry_new ();
52   tmp_lat = g_strdup_printf ( "%f", old->lat );
53   gtk_entry_set_text ( GTK_ENTRY(lat), tmp_lat );
54   g_free ( tmp_lat );
55
56   lonlabel = gtk_label_new ("Longitude:");
57   lon = gtk_entry_new ();
58   tmp_lon = g_strdup_printf ( "%f", old->lon );
59   gtk_entry_set_text ( GTK_ENTRY(lon), tmp_lon );
60   g_free ( tmp_lon );
61
62   gtk_widget_show ( latlabel );
63   gtk_widget_show ( lonlabel );
64   gtk_widget_show ( lat );
65   gtk_widget_show ( lon );
66
67   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latlabel,  FALSE, FALSE, 0);
68   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lat, FALSE, FALSE, 0);
69   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonlabel,  FALSE, FALSE, 0);
70   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lon,  FALSE, FALSE, 0);
71
72   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
73   {
74     ll->lat = atof ( gtk_entry_get_text ( GTK_ENTRY(lat) ) );
75     ll->lon = atof ( gtk_entry_get_text ( GTK_ENTRY(lon) ) );
76     gtk_widget_destroy ( dialog );
77     return TRUE;
78   }
79
80   gtk_widget_destroy ( dialog );
81   return FALSE;
82 }
83
84 gboolean a_dialog_goto_utm ( GtkWindow *parent, struct UTM *utm, const struct UTM *old )
85 {
86   GtkWidget *dialog = gtk_dialog_new_with_buttons ("Go to Lat/Lon",
87                                                   parent,
88                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
89                                                   GTK_STOCK_CANCEL,
90                                                   GTK_RESPONSE_REJECT,
91                                                   GTK_STOCK_OK,
92                                                   GTK_RESPONSE_ACCEPT,
93                                                   NULL);
94   GtkWidget *norlabel, *easlabel, *nor, *eas;
95   GtkWidget *zonehbox, *zonespin, *letterentry;
96   gchar *tmp_eas, *tmp_nor;
97   gchar tmp_letter[2];
98
99   norlabel = gtk_label_new ("Northing:");
100   nor = gtk_entry_new ();
101   tmp_nor = g_strdup_printf("%ld", (long) old->northing );
102   gtk_entry_set_text ( GTK_ENTRY(nor), tmp_nor );
103   g_free ( tmp_nor );
104
105   easlabel = gtk_label_new ("Easting:");
106   eas = gtk_entry_new ();
107   tmp_eas = g_strdup_printf("%ld", (long) old->easting );
108   gtk_entry_set_text ( GTK_ENTRY(eas), tmp_eas );
109   g_free ( tmp_eas );
110
111   zonehbox = gtk_hbox_new ( FALSE, 0 );
112   gtk_box_pack_start ( GTK_BOX(zonehbox), gtk_label_new ( "Zone:" ), FALSE, FALSE, 5 );
113   zonespin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( old->zone, 1, 60, 1, 5, 5 ), 1, 0 );
114   gtk_box_pack_start ( GTK_BOX(zonehbox), zonespin, TRUE, TRUE, 5 );
115   gtk_box_pack_start ( GTK_BOX(zonehbox), gtk_label_new ( "Letter:" ), FALSE, FALSE, 5 );
116   letterentry = gtk_entry_new ();
117   gtk_entry_set_max_length ( GTK_ENTRY(letterentry), 1 );
118   gtk_entry_set_width_chars ( GTK_ENTRY(letterentry), 2 );
119   tmp_letter[0] = old->letter;
120   tmp_letter[1] = '\0';
121   gtk_entry_set_text ( GTK_ENTRY(letterentry), tmp_letter );
122   gtk_box_pack_start ( GTK_BOX(zonehbox), letterentry, FALSE, FALSE, 5 );
123
124   gtk_widget_show ( norlabel );
125   gtk_widget_show ( easlabel );
126   gtk_widget_show ( nor );
127   gtk_widget_show ( eas );
128
129   gtk_widget_show_all ( zonehbox );
130
131   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), norlabel, FALSE, FALSE, 0);
132   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), nor, FALSE, FALSE, 0);
133   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), easlabel,  FALSE, FALSE, 0);
134   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), eas,  FALSE, FALSE, 0);
135   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), zonehbox,  FALSE, FALSE, 0);
136
137   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
138   {
139     const gchar *letter;
140     utm->northing = atof ( gtk_entry_get_text ( GTK_ENTRY(nor) ) );
141     utm->easting = atof ( gtk_entry_get_text ( GTK_ENTRY(eas) ) );
142     utm->zone = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(zonespin) );
143     letter = gtk_entry_get_text ( GTK_ENTRY(letterentry) );
144     if (*letter)
145        utm->letter = toupper(*letter);
146     gtk_widget_destroy ( dialog );
147     return TRUE;
148   }
149
150   gtk_widget_destroy ( dialog );
151   return FALSE;
152 }
153
154 void a_dialog_response_accept ( GtkDialog *dialog )
155 {
156   gtk_dialog_response ( dialog, GTK_RESPONSE_ACCEPT );
157 }
158
159 /* todo: less on this side, like add track */
160 gboolean a_dialog_new_waypoint ( GtkWindow *parent, gchar **dest, VikWaypoint *wp, GHashTable *waypoints, VikCoordMode coord_mode )
161 {
162   GtkWidget *dialog = gtk_dialog_new_with_buttons ("Create",
163                                                    parent,
164                                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
165                                                    GTK_STOCK_CANCEL,
166                                                    GTK_RESPONSE_REJECT,
167                                                    GTK_STOCK_OK,
168                                                    GTK_RESPONSE_ACCEPT,
169                                                    NULL);
170   struct LatLon ll;
171   GtkWidget *latlabel, *lonlabel, *namelabel, *latentry, *lonentry, *altentry, *altlabel, *nameentry, *commentlabel, *commententry, *imagelabel, *imageentry;
172
173   gchar *lat, *lon, *alt;
174
175   vik_coord_to_latlon ( &(wp->coord), &ll );
176
177   lat = g_strdup_printf ( "%f", ll.lat );
178   lon = g_strdup_printf ( "%f", ll.lon );
179   alt = g_strdup_printf ( "%f", wp->altitude );
180
181   if ( dest != NULL )
182   {
183     namelabel = gtk_label_new ("Name:");
184     nameentry = gtk_entry_new ();
185     g_signal_connect_swapped ( nameentry, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
186     gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), namelabel, FALSE, FALSE, 0);
187     gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), nameentry, FALSE, FALSE, 0);
188   }
189
190   latlabel = gtk_label_new ("Latitude:");
191   latentry = gtk_entry_new ();
192   gtk_entry_set_text ( GTK_ENTRY(latentry), lat );
193   g_free ( lat );
194
195   lonlabel = gtk_label_new ("Longitude:");
196   lonentry = gtk_entry_new ();
197   gtk_entry_set_text ( GTK_ENTRY(lonentry), lon );
198   g_free ( lon );
199
200   altlabel = gtk_label_new ("Altitude:");
201   altentry = gtk_entry_new ();
202   gtk_entry_set_text ( GTK_ENTRY(altentry), alt );
203   g_free ( alt );
204
205   commentlabel = gtk_label_new ("Comment:");
206   commententry = gtk_entry_new ();
207
208   imagelabel = gtk_label_new ("Image:");
209   imageentry = vik_file_entry_new ();
210
211   if ( dest == NULL && wp->comment )
212     gtk_entry_set_text ( GTK_ENTRY(commententry), wp->comment );
213
214   if ( dest == NULL && wp->image )
215     vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), wp->image );
216
217   
218
219   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latlabel, FALSE, FALSE, 0);
220   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latentry, FALSE, FALSE, 0);
221   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonlabel, FALSE, FALSE, 0);
222   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonentry, FALSE, FALSE, 0);
223   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), altlabel, FALSE, FALSE, 0);
224   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), altentry, FALSE, FALSE, 0);
225   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), commentlabel, FALSE, FALSE, 0);
226   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), commententry, FALSE, FALSE, 0);
227   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), imagelabel, FALSE, FALSE, 0);
228   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), imageentry, FALSE, FALSE, 0);
229
230   gtk_widget_show_all ( GTK_DIALOG(dialog)->vbox );
231         
232   while ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
233   {
234     if ( dest )
235     {
236       const gchar *constname = gtk_entry_get_text ( GTK_ENTRY(nameentry) );
237       if ( strlen(constname) == 0 ) /* TODO: other checks (isalpha or whatever ) */
238         a_dialog_info_msg ( parent, "Please enter a name for the waypoint." );
239       else {
240         int i;
241         gchar *name = g_strdup ( constname );
242
243         for ( i = strlen ( name ) - 1; i >= 0; i-- )
244           name[i] = toupper(name[i]); /* all caps for stardandization */
245
246         if ( g_hash_table_lookup ( waypoints, name ) && !a_dialog_overwrite ( parent, "The waypoint \"%s\" exists, do you want to overwrite it?", name ) )
247           g_free ( name );
248         else
249         {
250           /* Do It */
251           *dest = name;
252           ll.lat = atof ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
253           ll.lon = atof ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
254           vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
255           wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
256           vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
257           vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
258           if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
259             a_thumbnails_create ( wp->image );
260           gtk_widget_destroy ( dialog );
261           return TRUE;
262         }
263       } /* else (valid name) */
264     }
265     else
266     {
267       ll.lat = atof ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
268       ll.lon = atof ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
269       vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
270       wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
271       if ( (! wp->comment) || strcmp ( wp->comment, gtk_entry_get_text ( GTK_ENTRY(commententry) ) ) != 0 )
272         vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
273       if ( (! wp->image) || strcmp ( wp->image, vik_file_entry_get_filename ( VIK_FILE_ENTRY ( imageentry ) ) ) != 0 )
274       {
275         vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
276         if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
277           a_thumbnails_create ( wp->image );
278       }
279
280       gtk_widget_destroy ( dialog );
281
282       return TRUE;
283     }
284   }
285   gtk_widget_destroy ( dialog );
286   return FALSE;
287 }
288
289 gchar *a_dialog_new_track ( GtkWindow *parent, GHashTable *tracks )
290 {
291   GtkWidget *dialog = gtk_dialog_new_with_buttons ("Add Track",
292                                                   parent,
293                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
294                                                   GTK_STOCK_CANCEL,
295                                                   GTK_RESPONSE_REJECT,
296                                                   GTK_STOCK_OK,
297                                                   GTK_RESPONSE_ACCEPT,
298                                                   NULL);
299   GtkWidget *label = gtk_label_new ( "Track Name:" );
300   GtkWidget *entry = gtk_entry_new ();
301
302   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0);
303   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, FALSE, FALSE, 0);
304
305   g_signal_connect_swapped ( entry, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
306
307   gtk_widget_show ( label );
308   gtk_widget_show ( entry );
309
310   while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT )
311   {
312     const gchar *constname = gtk_entry_get_text ( GTK_ENTRY(entry) );
313     if ( *constname == '\0' )
314       a_dialog_info_msg ( parent, "Please enter a name for the track." );
315     else {
316       gchar *name = g_strdup ( constname );
317       gint i;
318
319       for ( i = strlen ( name ) - 1; i >= 0; i-- )
320         name[i] = toupper(name[i]); /* all caps for stardandization */
321
322       if ( g_hash_table_lookup( tracks, name ) && !a_dialog_overwrite ( parent, "The track \"%s\" exists, do you want to overwrite it?", gtk_entry_get_text ( GTK_ENTRY(entry) ) ) )
323       {
324         g_free ( name );
325       }
326       else
327       {
328         gtk_widget_destroy ( dialog );
329         return name;
330       }
331     }
332   }
333   gtk_widget_destroy ( dialog );
334   return NULL;
335 }
336
337 /* creates a vbox full of labels */
338 GtkWidget *a_dialog_create_label_vbox ( gchar **texts, int label_count )
339 {
340   GtkWidget *vbox, *label;
341   int i;
342   vbox = gtk_vbox_new( TRUE, 3 );
343
344   for ( i = 0; i < label_count; i++ )
345   {
346     label = gtk_label_new(NULL);
347     gtk_label_set_markup ( GTK_LABEL(label), texts[i] );
348     gtk_box_pack_start ( GTK_BOX(vbox), label, FALSE, TRUE, 5 );
349   }
350   return vbox;
351 }
352
353 gboolean a_dialog_overwrite ( GtkWindow *parent, const gchar *message, const gchar *extra )
354 {
355   GtkWidget *dia;
356   dia = gtk_message_dialog_new ( parent,
357                                  GTK_DIALOG_DESTROY_WITH_PARENT,
358                                  GTK_MESSAGE_QUESTION,
359                                  GTK_BUTTONS_YES_NO,
360                                  message, extra );
361
362   if ( gtk_dialog_run ( GTK_DIALOG(dia) ) == GTK_RESPONSE_YES )
363   {
364     gtk_widget_destroy ( dia );
365     return TRUE;
366   }
367   else
368   {
369     gtk_widget_destroy ( dia );
370     return FALSE;
371   }
372 }
373
374 static void zoom_spin_changed ( GtkSpinButton *spin, GtkWidget *pass_along[3] )
375 {
376   if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(pass_along[2]) ) )
377     gtk_spin_button_set_value ( 
378         GTK_SPIN_BUTTON(pass_along[GTK_WIDGET(spin) == pass_along[0] ? 1 : 0]),
379         gtk_spin_button_get_value ( spin ) );
380 }
381
382 gboolean a_dialog_custom_zoom ( GtkWindow *parent, gdouble *xmpp, gdouble *ympp )
383 {
384   GtkWidget *dialog = gtk_dialog_new_with_buttons ("Zoom Factors...",
385                                                   parent,
386                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
387                                                   GTK_STOCK_CANCEL,
388                                                   GTK_RESPONSE_REJECT,
389                                                   GTK_STOCK_OK,
390                                                   GTK_RESPONSE_ACCEPT,
391                                                   NULL);
392   GtkWidget *table, *label, *xlabel, *xspin, *ylabel, *yspin, *samecheck;
393   GtkWidget *pass_along[3];
394
395   table = gtk_table_new ( 4, 2, FALSE );
396   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
397
398   label = gtk_label_new ( "Zoom factor (in meters per pixel:" );
399   xlabel = gtk_label_new ( "X (easting): ");
400   ylabel = gtk_label_new ( "Y (northing): ");
401
402   pass_along[0] = xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( *xmpp, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 5 ), 1, 8 );
403   pass_along[1] = yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( *ympp, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 5 ), 1, 8 );
404
405   pass_along[2] = samecheck = gtk_check_button_new_with_label ( "X and Y zoom factors must be equal" );
406   /* TODO -- same factor */
407   /*  samecheck = gtk_check_button_new_with_label ( "Same x/y zoom factor" ); */
408
409   if ( *xmpp == *ympp )
410     gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(samecheck), TRUE );
411
412   gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 2, 0, 1 );
413   gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 1, 2 );
414   gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 1, 2 );
415   gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 2, 3 );
416   gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 2, 3 );
417   gtk_table_attach_defaults ( GTK_TABLE(table), samecheck, 0, 2, 3, 4 );
418
419   gtk_widget_show_all ( table );
420
421   g_signal_connect ( G_OBJECT(xspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
422   g_signal_connect ( G_OBJECT(yspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
423
424   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
425   {
426     *xmpp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
427     *ympp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
428     gtk_widget_destroy ( dialog );
429     return TRUE;
430   }
431   gtk_widget_destroy ( dialog );
432   return FALSE;
433 }