]> git.street.me.uk Git - andy/viking.git/blob - src/dialog.c
[QA] Add ifdef macro for Google Directions related
[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  * Copyright (C) 2008, Hein Ragas <viking@ragas.nl>
6  * Copyright (C) 2010, 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
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "viking.h"
29 #include "thumbnails.h"
30 #include "garminsymbols.h"
31 #include "degrees_converters.h"
32 #include "authors.h"
33 #include "documenters.h"
34 #include "vikgoto.h"
35 #include "util.h"
36
37 #include <glib/gi18n.h>
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42
43 void a_dialog_msg ( GtkWindow *parent, gint type, const gchar *info, const gchar *extra )
44 {
45   GtkWidget *msgbox = gtk_message_dialog_new ( parent, GTK_DIALOG_DESTROY_WITH_PARENT, type, GTK_BUTTONS_OK, info, extra );
46   gtk_dialog_run ( GTK_DIALOG(msgbox) );
47   gtk_widget_destroy ( msgbox );
48 }
49
50 gboolean a_dialog_goto_latlon ( GtkWindow *parent, struct LatLon *ll, const struct LatLon *old )
51 {
52   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Go to Lat/Lon"),
53                                                   parent,
54                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
55                                                   GTK_STOCK_CANCEL,
56                                                   GTK_RESPONSE_REJECT,
57                                                   GTK_STOCK_OK,
58                                                   GTK_RESPONSE_ACCEPT,
59                                                   NULL);
60   GtkWidget *latlabel, *lonlabel;
61   GtkWidget *lat, *lon;
62   gchar *tmp_lat, *tmp_lon;
63
64   latlabel = gtk_label_new (_("Latitude:"));
65   lat = gtk_entry_new ();
66   tmp_lat = g_strdup_printf ( "%f", old->lat );
67   gtk_entry_set_text ( GTK_ENTRY(lat), tmp_lat );
68   g_free ( tmp_lat );
69
70   lonlabel = gtk_label_new (_("Longitude:"));
71   lon = gtk_entry_new ();
72   tmp_lon = g_strdup_printf ( "%f", old->lon );
73   gtk_entry_set_text ( GTK_ENTRY(lon), tmp_lon );
74   g_free ( tmp_lon );
75
76   gtk_widget_show ( latlabel );
77   gtk_widget_show ( lonlabel );
78   gtk_widget_show ( lat );
79   gtk_widget_show ( lon );
80
81   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latlabel,  FALSE, FALSE, 0);
82   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lat, FALSE, FALSE, 0);
83   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonlabel,  FALSE, FALSE, 0);
84   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lon,  FALSE, FALSE, 0);
85
86   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
87
88   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
89   {
90     ll->lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lat) ) );
91     ll->lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lon) ) );
92     gtk_widget_destroy ( dialog );
93     return TRUE;
94   }
95
96   gtk_widget_destroy ( dialog );
97   return FALSE;
98 }
99
100 gboolean a_dialog_goto_utm ( GtkWindow *parent, struct UTM *utm, const struct UTM *old )
101 {
102   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Go to UTM"),
103                                                   parent,
104                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
105                                                   GTK_STOCK_CANCEL,
106                                                   GTK_RESPONSE_REJECT,
107                                                   GTK_STOCK_OK,
108                                                   GTK_RESPONSE_ACCEPT,
109                                                   NULL);
110   GtkWidget *norlabel, *easlabel, *nor, *eas;
111   GtkWidget *zonehbox, *zonespin, *letterentry;
112   gchar *tmp_eas, *tmp_nor;
113   gchar tmp_letter[2];
114
115   norlabel = gtk_label_new (_("Northing:"));
116   nor = gtk_entry_new ();
117   tmp_nor = g_strdup_printf("%ld", (long) old->northing );
118   gtk_entry_set_text ( GTK_ENTRY(nor), tmp_nor );
119   g_free ( tmp_nor );
120
121   easlabel = gtk_label_new (_("Easting:"));
122   eas = gtk_entry_new ();
123   tmp_eas = g_strdup_printf("%ld", (long) old->easting );
124   gtk_entry_set_text ( GTK_ENTRY(eas), tmp_eas );
125   g_free ( tmp_eas );
126
127   zonehbox = gtk_hbox_new ( FALSE, 0 );
128   gtk_box_pack_start ( GTK_BOX(zonehbox), gtk_label_new ( _("Zone:") ), FALSE, FALSE, 5 );
129   zonespin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( old->zone, 1, 60, 1, 5, 0 ), 1, 0 );
130   gtk_box_pack_start ( GTK_BOX(zonehbox), zonespin, TRUE, TRUE, 5 );
131   gtk_box_pack_start ( GTK_BOX(zonehbox), gtk_label_new ( _("Letter:") ), FALSE, FALSE, 5 );
132   letterentry = gtk_entry_new ();
133   gtk_entry_set_max_length ( GTK_ENTRY(letterentry), 1 );
134   gtk_entry_set_width_chars ( GTK_ENTRY(letterentry), 2 );
135   tmp_letter[0] = old->letter;
136   tmp_letter[1] = '\0';
137   gtk_entry_set_text ( GTK_ENTRY(letterentry), tmp_letter );
138   gtk_box_pack_start ( GTK_BOX(zonehbox), letterentry, FALSE, FALSE, 5 );
139
140   gtk_widget_show ( norlabel );
141   gtk_widget_show ( easlabel );
142   gtk_widget_show ( nor );
143   gtk_widget_show ( eas );
144
145   gtk_widget_show_all ( zonehbox );
146
147   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), norlabel, FALSE, FALSE, 0);
148   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), nor, FALSE, FALSE, 0);
149   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), easlabel,  FALSE, FALSE, 0);
150   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), eas,  FALSE, FALSE, 0);
151   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), zonehbox,  FALSE, FALSE, 0);
152
153   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
154
155   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
156   {
157     const gchar *letter;
158     utm->northing = atof ( gtk_entry_get_text ( GTK_ENTRY(nor) ) );
159     utm->easting = atof ( gtk_entry_get_text ( GTK_ENTRY(eas) ) );
160     utm->zone = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(zonespin) );
161     letter = gtk_entry_get_text ( GTK_ENTRY(letterentry) );
162     if (*letter)
163        utm->letter = toupper(*letter);
164     gtk_widget_destroy ( dialog );
165     return TRUE;
166   }
167
168   gtk_widget_destroy ( dialog );
169   return FALSE;
170 }
171
172 void a_dialog_response_accept ( GtkDialog *dialog )
173 {
174   gtk_dialog_response ( dialog, GTK_RESPONSE_ACCEPT );
175 }
176
177 static void symbol_entry_changed_cb(GtkWidget *combo, GtkListStore *store)
178 {
179   GtkTreeIter iter;
180   gchar *sym;
181
182   if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter))
183     return;
184
185   gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
186   /* Note: symm is NULL when "(none)" is select (first cell is empty) */
187   gtk_widget_set_tooltip_text(combo, sym);
188   g_free(sym);
189 }
190
191 /* Specify if a new waypoint or not */
192 /* If a new waypoint then it uses the default_name for the suggested name allowing the user to change it.
193     The name to use is returned
194    When an existing waypoint the default name is shown but is not allowed to be changed and NULL is returned
195  */
196 /* todo: less on this side, like add track */
197 gchar *a_dialog_waypoint ( GtkWindow *parent, gchar *default_name, VikWaypoint *wp, VikCoordMode coord_mode, gboolean is_new, gboolean *updated )
198 {
199   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Waypoint Properties"),
200                                                    parent,
201                                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
202                                                    GTK_STOCK_CANCEL,
203                                                    GTK_RESPONSE_REJECT,
204                                                    GTK_STOCK_OK,
205                                                    GTK_RESPONSE_ACCEPT,
206                                                    NULL);
207   struct LatLon ll;
208   GtkWidget *latlabel, *lonlabel, *namelabel, *latentry, *lonentry, *altentry, *altlabel, *nameentry=NULL;
209   GtkWidget *commentlabel, *commententry, *descriptionlabel, *descriptionentry, *imagelabel, *imageentry, *symbollabel, *symbolentry;
210   GtkListStore *store;
211
212   gchar *lat, *lon, *alt;
213
214   vik_coord_to_latlon ( &(wp->coord), &ll );
215
216   lat = g_strdup_printf ( "%f", ll.lat );
217   lon = g_strdup_printf ( "%f", ll.lon );
218   vik_units_height_t height_units = a_vik_get_units_height ();
219   switch (height_units) {
220   case VIK_UNITS_HEIGHT_METRES:
221     alt = g_strdup_printf ( "%f", wp->altitude );
222     break;
223   case VIK_UNITS_HEIGHT_FEET:
224     alt = g_strdup_printf ( "%f", VIK_METERS_TO_FEET(wp->altitude) );
225     break;
226   default:
227     alt = g_strdup_printf ( "%f", wp->altitude );
228     g_critical("Houston, we've had a problem. height=%d", height_units);
229   }
230
231   *updated = FALSE;
232
233   namelabel = gtk_label_new (_("Name:"));
234   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), namelabel, FALSE, FALSE, 0);
235   if ( is_new )
236   {
237     // New waypoint, so name is still changeable
238     nameentry = gtk_entry_new ();
239     if ( default_name )
240       gtk_entry_set_text( GTK_ENTRY(nameentry), default_name );
241     g_signal_connect_swapped ( nameentry, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
242   }
243   else {
244     // Existing waypoint - so can not change the name this way - but at least can see it
245     if ( default_name )
246       nameentry = gtk_label_new ( default_name );
247   }
248   if ( nameentry )
249     gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), nameentry, FALSE, FALSE, 0);
250
251   latlabel = gtk_label_new (_("Latitude:"));
252   latentry = gtk_entry_new ();
253   gtk_entry_set_text ( GTK_ENTRY(latentry), lat );
254   g_free ( lat );
255
256   lonlabel = gtk_label_new (_("Longitude:"));
257   lonentry = gtk_entry_new ();
258   gtk_entry_set_text ( GTK_ENTRY(lonentry), lon );
259   g_free ( lon );
260
261   altlabel = gtk_label_new (_("Altitude:"));
262   altentry = gtk_entry_new ();
263   gtk_entry_set_text ( GTK_ENTRY(altentry), alt );
264   g_free ( alt );
265
266   commentlabel = gtk_label_new (_("Comment:"));
267   commententry = gtk_entry_new ();
268   gchar *cmt =  NULL;
269   // Auto put in some kind of 'name' as a comment if one previously 'goto'ed this exact location
270   cmt = a_vik_goto_get_search_string_for_this_place(VIK_WINDOW(parent));
271   if (cmt)
272     gtk_entry_set_text(GTK_ENTRY(commententry), cmt);
273
274   descriptionlabel = gtk_label_new (_("Description:"));
275   descriptionentry = gtk_entry_new ();
276
277   imagelabel = gtk_label_new (_("Image:"));
278   imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
279
280   {
281     GtkCellRenderer *r;
282     symbollabel = gtk_label_new (_("Symbol:"));
283     GtkTreeIter iter;
284
285     store = gtk_list_store_new(3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING);
286     symbolentry = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
287     gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(symbolentry), 6);
288
289     g_signal_connect(symbolentry, "changed", G_CALLBACK(symbol_entry_changed_cb), store);
290     gtk_list_store_append (store, &iter);
291     gtk_list_store_set (store, &iter, 0, NULL, 1, NULL, 2, _("(none)"), -1);
292     a_populate_sym_list(store);
293
294     r = gtk_cell_renderer_pixbuf_new ();
295     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (symbolentry), r, FALSE);
296     gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (symbolentry), r, "pixbuf", 1, NULL);
297
298     r = gtk_cell_renderer_text_new ();
299     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (symbolentry), r, FALSE);
300     gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (symbolentry), r, "text", 2, NULL);
301
302     if ( !is_new && wp->symbol ) {
303       gboolean ok;
304       gchar *sym;
305       for (ok = gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &iter ); ok; ok = gtk_tree_model_iter_next ( GTK_TREE_MODEL(store), &iter)) {
306         gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
307         if (sym && !strcmp(sym, wp->symbol)) {
308           g_free(sym);
309           break;
310         } else {
311           g_free(sym);
312         }
313       }
314       // Ensure is it a valid symbol in the given symbol set (large vs small)
315       // Not all symbols are available in both
316       // The check prevents a Gtk Critical message
317       if ( iter.stamp )
318         gtk_combo_box_set_active_iter(GTK_COMBO_BOX(symbolentry), &iter);
319     }
320   }
321
322   if ( !is_new && wp->comment )
323     gtk_entry_set_text ( GTK_ENTRY(commententry), wp->comment );
324
325   if ( !is_new && wp->description )
326     gtk_entry_set_text ( GTK_ENTRY(descriptionentry), wp->description );
327
328   if ( !is_new && wp->image )
329     vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), wp->image );
330
331
332   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latlabel, FALSE, FALSE, 0);
333   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latentry, FALSE, FALSE, 0);
334   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonlabel, FALSE, FALSE, 0);
335   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonentry, FALSE, FALSE, 0);
336   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), altlabel, FALSE, FALSE, 0);
337   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), altentry, FALSE, FALSE, 0);
338   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), commentlabel, FALSE, FALSE, 0);
339   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), commententry, FALSE, FALSE, 0);
340   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), descriptionlabel, FALSE, FALSE, 0);
341   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), descriptionentry, FALSE, FALSE, 0);
342   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), imagelabel, FALSE, FALSE, 0);
343   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), imageentry, FALSE, FALSE, 0);
344   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), symbollabel, FALSE, FALSE, 0);
345   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(symbolentry), FALSE, FALSE, 0);
346
347   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
348
349   gtk_widget_show_all ( GTK_DIALOG(dialog)->vbox );
350
351   while ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
352   {
353     if ( is_new )
354     {
355       gchar *entered_name = g_strdup ( (gchar*)gtk_entry_get_text ( GTK_ENTRY(nameentry) ) );
356       if ( strlen(entered_name) == 0 ) /* TODO: other checks (isalpha or whatever ) */
357         a_dialog_info_msg ( parent, _("Please enter a name for the waypoint.") );
358       else {
359
360         // NB: No check for unique names - this allows generation of same named entries.
361
362         /* Do It */
363         ll.lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
364         ll.lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
365         vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
366         // Always store in metres
367         switch (height_units) {
368         case VIK_UNITS_HEIGHT_METRES:
369           wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
370           break;
371         case VIK_UNITS_HEIGHT_FEET:
372           wp->altitude = VIK_FEET_TO_METERS(atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) ));
373           break;
374         default:
375           wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
376           g_critical("Houston, we've had a problem. height=%d", height_units);
377         }
378         vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
379         vik_waypoint_set_description ( wp, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) );
380         vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
381         if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
382           a_thumbnails_create ( wp->image );
383
384         GtkTreeIter iter, first;
385         gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &first );
386         if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX(symbolentry), &iter ) || !memcmp(&iter, &first, sizeof(GtkTreeIter)) ) {
387           vik_waypoint_set_symbol ( wp, NULL );
388         } else {
389           gchar *sym;
390           gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
391           vik_waypoint_set_symbol ( wp, sym );
392           g_free(sym);
393         }
394
395         gtk_widget_destroy ( dialog );
396         return entered_name;
397       }
398     }
399     else
400     {
401       ll.lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
402       ll.lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
403       vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
404       switch (height_units) {
405       case VIK_UNITS_HEIGHT_METRES:
406         wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
407         break;
408       case VIK_UNITS_HEIGHT_FEET:
409         wp->altitude = VIK_FEET_TO_METERS(atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) ));
410         break;
411       default:
412         wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
413         g_critical("Houston, we've had a problem. height=%d", height_units);
414       }
415       if ( (! wp->comment) || strcmp ( wp->comment, gtk_entry_get_text ( GTK_ENTRY(commententry) ) ) != 0 )
416         vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
417       if ( (! wp->description) || strcmp ( wp->description, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) ) != 0 )
418         vik_waypoint_set_description ( wp, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) );
419       if ( (! wp->image) || strcmp ( wp->image, vik_file_entry_get_filename ( VIK_FILE_ENTRY ( imageentry ) ) ) != 0 )
420       {
421         vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
422         if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
423           a_thumbnails_create ( wp->image );
424       }
425
426       {
427         GtkTreeIter iter, first;
428         gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &first );
429         if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX(symbolentry), &iter ) || !memcmp(&iter, &first, sizeof(GtkTreeIter)) ) {
430           vik_waypoint_set_symbol ( wp, NULL );
431         } else {
432           gchar *sym;
433           gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
434           vik_waypoint_set_symbol ( wp, sym );
435           g_free(sym);
436         }
437       }         
438
439       gtk_widget_destroy ( dialog );
440       
441       *updated = TRUE;
442       return NULL;
443     }
444   }
445   gtk_widget_destroy ( dialog );
446   return NULL;
447 }
448
449 static void get_selected_foreach_func(GtkTreeModel *model,
450                                       GtkTreePath *path,
451                                       GtkTreeIter *iter,
452                                       gpointer data)
453 {
454   GList **list = data;
455   gchar *name;
456   gtk_tree_model_get (model, iter, 0, &name, -1);
457   *list = g_list_prepend(*list, name);
458 }
459
460 GList *a_dialog_select_from_list ( GtkWindow *parent, GList *names, gboolean multiple_selection_allowed, const gchar *title, const gchar *msg )
461 {
462   GtkTreeIter iter;
463   GtkCellRenderer *renderer;
464   GtkWidget *view;
465
466   GtkWidget *dialog = gtk_dialog_new_with_buttons (title,
467                                                   parent,
468                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
469                                                   GTK_STOCK_CANCEL,
470                                                   GTK_RESPONSE_REJECT,
471                                                   GTK_STOCK_OK,
472                                                   GTK_RESPONSE_ACCEPT,
473                                                   NULL);
474   /* When something is selected then OK */
475   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
476   GtkWidget *response_w = NULL;
477 #if GTK_CHECK_VERSION (2, 20, 0)
478   /* Default to not apply - as initially nothing is selected! */
479   response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
480 #endif
481   GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING);
482
483   GtkWidget *scrolledwindow;
484
485   GList *runner = names;
486   while (runner)
487   {
488     gtk_list_store_append(store, &iter);
489     gtk_list_store_set(store, &iter, 0, runner->data, -1);
490     runner = g_list_next(runner);
491   }
492
493   view = gtk_tree_view_new();
494   renderer = gtk_cell_renderer_text_new();
495   // Use the column header to display the message text,
496   // this makes the overall widget allocation simple as treeview takes up all the space
497   gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(view), -1, msg, renderer, "text", 0, NULL);
498   gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
499   gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(view), TRUE);
500   gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
501       multiple_selection_allowed ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE );
502   g_object_unref(store);
503
504   scrolledwindow = gtk_scrolled_window_new ( NULL, NULL );
505   gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
506   gtk_container_add ( GTK_CONTAINER(scrolledwindow), view );
507
508   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolledwindow, TRUE, TRUE, 0 );
509   // Ensure a reasonable number of items are shown, but let the width be automatically sized
510   gtk_widget_set_size_request ( dialog, -1, 400) ;
511
512   gtk_widget_show_all ( dialog );
513
514   if ( response_w )
515     gtk_widget_grab_focus ( response_w );
516
517   while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT )
518   {
519     GList *names = NULL;
520     GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
521     gtk_tree_selection_selected_foreach(selection, get_selected_foreach_func, &names);
522     if (names)
523     {
524       gtk_widget_destroy ( dialog );
525       return (names);
526     }
527     a_dialog_error_msg(parent, _("Nothing was selected"));
528   }
529   gtk_widget_destroy ( dialog );
530   return NULL;
531 }
532
533 gchar *a_dialog_new_track ( GtkWindow *parent, GHashTable *tracks, gchar *default_name )
534 {
535   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Add Track"),
536                                                   parent,
537                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
538                                                   GTK_STOCK_CANCEL,
539                                                   GTK_RESPONSE_REJECT,
540                                                   GTK_STOCK_OK,
541                                                   GTK_RESPONSE_ACCEPT,
542                                                   NULL);
543   GtkWidget *label = gtk_label_new ( _("Track Name:") );
544   GtkWidget *entry = gtk_entry_new ();
545
546   if (default_name)
547     gtk_entry_set_text ( GTK_ENTRY(entry), default_name );
548
549   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0);
550   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, FALSE, FALSE, 0);
551
552   g_signal_connect_swapped ( entry, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
553
554   gtk_widget_show ( label );
555   gtk_widget_show ( entry );
556
557   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
558
559   while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT )
560   {
561     const gchar *constname = gtk_entry_get_text ( GTK_ENTRY(entry) );
562     if ( *constname == '\0' )
563       a_dialog_info_msg ( parent, _("Please enter a name for the track.") );
564     else {
565       gchar *name = g_strdup ( constname );
566
567       if ( g_hash_table_lookup( tracks, name ) && !a_dialog_yes_or_no ( parent, _("The track \"%s\" exists, do you want to overwrite it?"), gtk_entry_get_text ( GTK_ENTRY(entry) ) ) )
568       {
569         g_free ( name );
570       }
571       else
572       {
573         gtk_widget_destroy ( dialog );
574         return name;
575       }
576     }
577   }
578   gtk_widget_destroy ( dialog );
579   return NULL;
580 }
581
582 /* creates a vbox full of labels */
583 GtkWidget *a_dialog_create_label_vbox ( gchar **texts, int label_count )
584 {
585   GtkWidget *vbox, *label;
586   int i;
587   vbox = gtk_vbox_new( TRUE, 3 );
588
589   for ( i = 0; i < label_count; i++ )
590   {
591     label = gtk_label_new(NULL);
592     gtk_label_set_markup ( GTK_LABEL(label), _(texts[i]) );
593     gtk_box_pack_start ( GTK_BOX(vbox), label, FALSE, TRUE, 5 );
594   }
595   return vbox;
596 }
597
598 gboolean a_dialog_yes_or_no ( GtkWindow *parent, const gchar *message, const gchar *extra )
599 {
600   GtkWidget *dia;
601   dia = gtk_message_dialog_new ( parent,
602                                  GTK_DIALOG_DESTROY_WITH_PARENT,
603                                  GTK_MESSAGE_QUESTION,
604                                  GTK_BUTTONS_YES_NO,
605                                  message, extra );
606
607   if ( gtk_dialog_run ( GTK_DIALOG(dia) ) == GTK_RESPONSE_YES )
608   {
609     gtk_widget_destroy ( dia );
610     return TRUE;
611   }
612   else
613   {
614     gtk_widget_destroy ( dia );
615     return FALSE;
616   }
617 }
618
619 static void zoom_spin_changed ( GtkSpinButton *spin, GtkWidget *pass_along[3] )
620 {
621   if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(pass_along[2]) ) )
622     gtk_spin_button_set_value ( 
623         GTK_SPIN_BUTTON(pass_along[GTK_WIDGET(spin) == pass_along[0] ? 1 : 0]),
624         gtk_spin_button_get_value ( spin ) );
625 }
626
627 gboolean a_dialog_custom_zoom ( GtkWindow *parent, gdouble *xmpp, gdouble *ympp )
628 {
629   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Zoom Factors..."),
630                                                   parent,
631                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
632                                                   GTK_STOCK_CANCEL,
633                                                   GTK_RESPONSE_REJECT,
634                                                   GTK_STOCK_OK,
635                                                   GTK_RESPONSE_ACCEPT,
636                                                   NULL);
637   GtkWidget *table, *label, *xlabel, *xspin, *ylabel, *yspin, *samecheck;
638   GtkWidget *pass_along[3];
639
640   table = gtk_table_new ( 4, 2, FALSE );
641   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
642
643   label = gtk_label_new ( _("Zoom factor (in meters per pixel):") );
644   xlabel = gtk_label_new ( _("X (easting): "));
645   ylabel = gtk_label_new ( _("Y (northing): "));
646
647   pass_along[0] = xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( *xmpp, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
648   pass_along[1] = yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( *ympp, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
649
650   pass_along[2] = samecheck = gtk_check_button_new_with_label ( _("X and Y zoom factors must be equal") );
651   /* TODO -- same factor */
652   /*  samecheck = gtk_check_button_new_with_label ( "Same x/y zoom factor" ); */
653
654   if ( *xmpp == *ympp )
655     gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(samecheck), TRUE );
656
657   gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 2, 0, 1 );
658   gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 1, 2 );
659   gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 1, 2 );
660   gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 2, 3 );
661   gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 2, 3 );
662   gtk_table_attach_defaults ( GTK_TABLE(table), samecheck, 0, 2, 3, 4 );
663
664   gtk_widget_show_all ( table );
665
666   g_signal_connect ( G_OBJECT(xspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
667   g_signal_connect ( G_OBJECT(yspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
668
669   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
670
671   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
672   {
673     *xmpp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
674     *ympp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
675     gtk_widget_destroy ( dialog );
676     return TRUE;
677   }
678   gtk_widget_destroy ( dialog );
679   return FALSE;
680 }
681
682 static void split_spin_focused ( GtkSpinButton *spin, GtkWidget *pass_along[1] )
683 {
684   gtk_toggle_button_set_active    (GTK_TOGGLE_BUTTON(pass_along[0]), 1);
685 }
686
687 gboolean a_dialog_time_threshold ( GtkWindow *parent, gchar *title_text, gchar *label_text, guint *thr )
688 {
689   GtkWidget *dialog = gtk_dialog_new_with_buttons (title_text, 
690                                                   parent,
691                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
692                                                   GTK_STOCK_CANCEL,
693                                                   GTK_RESPONSE_REJECT,
694                                                   GTK_STOCK_OK,
695                                                   GTK_RESPONSE_ACCEPT,
696                                                   NULL);
697   GtkWidget *table, *t1, *t2, *t3, *t4, *spin, *label;
698   GtkWidget *pass_along[1];
699
700   table = gtk_table_new ( 4, 2, FALSE );
701   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
702
703   label = gtk_label_new (label_text);
704
705   t1 = gtk_radio_button_new_with_label ( NULL, _("1 min") );
706   t2 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t1), _("1 hour") );
707   t3 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t2), _("1 day") );
708   t4 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t3), _("Custom (in minutes):") );
709
710   pass_along[0] = t4;
711
712   spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( *thr, 0, 65536, 1, 5, 0 ), 1, 0 );
713
714   gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 2, 0, 1 );
715   gtk_table_attach_defaults ( GTK_TABLE(table), t1, 0, 1, 1, 2 );
716   gtk_table_attach_defaults ( GTK_TABLE(table), t2, 0, 1, 2, 3 );
717   gtk_table_attach_defaults ( GTK_TABLE(table), t3, 0, 1, 3, 4 );
718   gtk_table_attach_defaults ( GTK_TABLE(table), t4, 0, 1, 4, 5 );
719   gtk_table_attach_defaults ( GTK_TABLE(table), spin, 1, 2, 4, 5 );
720
721   gtk_widget_show_all ( table );
722
723   g_signal_connect ( G_OBJECT(spin), "grab-focus", G_CALLBACK(split_spin_focused), pass_along );
724
725   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
726
727   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
728   {
729     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t1))) {
730       *thr = 1;
731     } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t2))) {
732       *thr = 60;
733     } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t3))) {
734       *thr = 60 * 24;
735     } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t4))) {
736       *thr = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(spin) );
737     }
738     gtk_widget_destroy ( dialog );
739     return TRUE;
740   }
741   gtk_widget_destroy ( dialog );
742   return FALSE;
743 }
744
745 /**
746  * Dialog to return a positive number via a spinbox within the supplied limits
747  * A return value of zero indicates the dialog was cancelled
748  */
749 guint a_dialog_get_positive_number ( GtkWindow *parent, gchar *title_text, gchar *label_text, guint default_num, guint min, guint max, guint step )
750 {
751   GtkWidget *dialog = gtk_dialog_new_with_buttons (title_text,
752                                                    parent,
753                                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
754                                                    GTK_STOCK_CANCEL,
755                                                    GTK_RESPONSE_REJECT,
756                                                    GTK_STOCK_OK,
757                                                    GTK_RESPONSE_ACCEPT,
758                                                    NULL);
759   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
760   GtkWidget *response_w = NULL;
761 #if GTK_CHECK_VERSION (2, 20, 0)
762   response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
763 #endif
764
765   GtkWidget *table, *spin, *label;
766   guint result = default_num;
767
768   table = gtk_table_new ( 2, 1, FALSE );
769   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
770
771   label = gtk_label_new (label_text);
772   spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( default_num, min, max, step, 5, 0 ), 1, 0 );
773
774   gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 1, 0, 1 );
775   gtk_table_attach_defaults ( GTK_TABLE(table), spin, 0, 1, 1, 2 );
776
777   if ( response_w )
778     gtk_widget_grab_focus ( response_w );
779
780   gtk_widget_show_all ( table );
781
782   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
783   {
784     result = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(spin) );
785     gtk_widget_destroy ( dialog );
786     return result;
787   }
788
789   // Dialog cancelled
790   gtk_widget_destroy ( dialog );
791   return 0;
792 }
793
794 static void about_url_hook (GtkAboutDialog *about,
795                             const gchar    *link,
796                             gpointer        data)
797 {
798   open_url (GTK_WINDOW(about), link);
799 }
800
801 static void about_email_hook (GtkAboutDialog *about,
802                               const gchar    *email,
803                               gpointer        data)
804 {
805   new_email (GTK_WINDOW(about), email);
806 }
807
808 void a_dialog_about ( GtkWindow *parent )
809 {
810   const gchar *program_name = PACKAGE_NAME;
811   const gchar *version = VIKING_VERSION;
812   const gchar *website = VIKING_URL;
813   const gchar *copyright = "2003-2008, Evan Battaglia\n2008-2010, Viking's contributors";
814   const gchar *comments = _("GPS Data and Topo Analyzer, Explorer, and Manager.");
815   const gchar *license = _("This program is free software; you can redistribute it and/or modify "
816                         "it under the terms of the GNU General Public License as published by "
817                         "the Free Software Foundation; either version 2 of the License, or "
818                         "(at your option) any later version."
819                         "\n\n"
820                         "This program is distributed in the hope that it will be useful, "
821                         "but WITHOUT ANY WARRANTY; without even the implied warranty of "
822                         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
823                         "GNU General Public License for more details."
824                         "\n\n"
825                         "You should have received a copy of the GNU General Public License "
826                         "along with this program; if not, write to the Free Software "
827                         "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA");
828
829   gtk_about_dialog_set_url_hook (about_url_hook, NULL, NULL);
830   gtk_about_dialog_set_email_hook (about_email_hook, NULL, NULL);
831   gtk_show_about_dialog (parent,
832         /* TODO do not set program-name and correctly set info for g_get_application_name */
833         "program-name", program_name,
834         "version", version,
835         "website", website,
836         "comments", comments,
837         "copyright", copyright,
838         "license", license,
839         "wrap-license", TRUE,
840         /* logo automatically retrieved via gtk_window_get_default_icon_list */
841         "authors", AUTHORS,
842         "documenters", DOCUMENTERS,
843         "translator-credits", _("Translation is coordinated on http://launchpad.net/viking"),
844         NULL);
845 }
846
847 gboolean a_dialog_map_n_zoom(GtkWindow *parent, gchar *mapnames[], gint default_map, gchar *zoom_list[], gint default_zoom, gint *selected_map, gint *selected_zoom)
848 {
849   gchar **s;
850
851   GtkWidget *dialog = gtk_dialog_new_with_buttons ( _("Download along track"), parent, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
852   gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
853   GtkWidget *response_w = NULL;
854 #if GTK_CHECK_VERSION (2, 20, 0)
855   response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
856 #endif
857   GtkWidget *map_label = gtk_label_new(_("Map type:"));
858   GtkComboBox *map_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
859   for (s = mapnames; *s; s++)
860     gtk_combo_box_append_text(map_combo, *s);
861   gtk_combo_box_set_active (map_combo, default_map);
862   GtkWidget *zoom_label = gtk_label_new(_("Zoom level:"));
863   GtkComboBox *zoom_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
864   for (s = zoom_list; *s; s++)
865     gtk_combo_box_append_text(zoom_combo, *s);
866   gtk_combo_box_set_active (zoom_combo, default_zoom);
867
868   GtkTable *box = GTK_TABLE(gtk_table_new(2, 2, FALSE));
869   gtk_table_attach_defaults(box, GTK_WIDGET(map_label), 0, 1, 0, 1);
870   gtk_table_attach_defaults(box, GTK_WIDGET(map_combo), 1, 2, 0, 1);
871   gtk_table_attach_defaults(box, GTK_WIDGET(zoom_label), 0, 1, 1, 2);
872   gtk_table_attach_defaults(box, GTK_WIDGET(zoom_combo), 1, 2, 1, 2);
873
874   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
875
876   if ( response_w )
877     gtk_widget_grab_focus ( response_w );
878
879   gtk_widget_show_all ( dialog );
880   if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
881     gtk_widget_destroy(dialog);
882     return FALSE;
883   }
884
885   *selected_map = gtk_combo_box_get_active(map_combo);
886   *selected_zoom = gtk_combo_box_get_active(zoom_combo);
887
888   gtk_widget_destroy(dialog);
889   return TRUE;
890 }
891
892 /**
893  * Display a dialog presenting the license of a map.
894  * Allow to read the license by launching a web browser.
895  */
896 void a_dialog_license ( GtkWindow *parent, const gchar *map, const gchar *license, const gchar *url)
897 {
898   GtkWidget *dialog = gtk_message_dialog_new (parent,
899                                  GTK_DIALOG_DESTROY_WITH_PARENT,
900                                  GTK_MESSAGE_INFO,
901                                  GTK_BUTTONS_OK,
902                                  _("The map data is licensed: %s."),
903                                  license);
904   gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
905     _("The data provided by '<b>%s</b>' are licensed under the following license: <b>%s</b>.\n"
906     "Please, read the license before continuing."),
907     map, license);
908 #define RESPONSE_OPEN_LICENSE 600
909   if (url != NULL) {
910     gtk_dialog_add_button (GTK_DIALOG (dialog), _("Open license"), RESPONSE_OPEN_LICENSE);
911   }
912   gint response;
913   do {
914     response = gtk_dialog_run (GTK_DIALOG (dialog));
915     if (response == RESPONSE_OPEN_LICENSE) {
916       open_url (parent, url);
917     }
918   } while (response != GTK_RESPONSE_DELETE_EVENT && response != GTK_RESPONSE_OK);
919   gtk_widget_destroy (dialog);
920 }