2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
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>
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.
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.
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
29 #include "thumbnails.h"
30 #include "garminsymbols.h"
31 #include "degrees_converters.h"
33 #include "documenters.h"
37 #include <glib/gi18n.h>
43 void a_dialog_msg ( GtkWindow *parent, gint type, const gchar *info, const gchar *extra )
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 );
50 gboolean a_dialog_goto_latlon ( GtkWindow *parent, struct LatLon *ll, const struct LatLon *old )
52 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Go to Lat/Lon"),
54 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
60 GtkWidget *latlabel, *lonlabel;
62 gchar *tmp_lat, *tmp_lon;
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 );
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 );
76 gtk_widget_show ( latlabel );
77 gtk_widget_show ( lonlabel );
78 gtk_widget_show ( lat );
79 gtk_widget_show ( lon );
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);
86 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
88 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
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 );
96 gtk_widget_destroy ( dialog );
100 gboolean a_dialog_goto_utm ( GtkWindow *parent, struct UTM *utm, const struct UTM *old )
102 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Go to UTM"),
104 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
110 GtkWidget *norlabel, *easlabel, *nor, *eas;
111 GtkWidget *zonehbox, *zonespin, *letterentry;
112 gchar *tmp_eas, *tmp_nor;
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 );
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 );
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 );
140 gtk_widget_show ( norlabel );
141 gtk_widget_show ( easlabel );
142 gtk_widget_show ( nor );
143 gtk_widget_show ( eas );
145 gtk_widget_show_all ( zonehbox );
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);
153 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
155 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
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) );
163 utm->letter = toupper(*letter);
164 gtk_widget_destroy ( dialog );
168 gtk_widget_destroy ( dialog );
172 void a_dialog_response_accept ( GtkDialog *dialog )
174 gtk_dialog_response ( dialog, GTK_RESPONSE_ACCEPT );
177 static void symbol_entry_changed_cb(GtkWidget *combo, GtkListStore *store)
182 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter))
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);
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
196 /* todo: less on this side, like add track */
197 gchar *a_dialog_waypoint ( GtkWindow *parent, gchar *default_name, VikWaypoint *wp, GHashTable *waypoints, VikCoordMode coord_mode, gboolean is_new, gboolean *updated )
199 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Waypoint Properties"),
201 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
208 GtkWidget *latlabel, *lonlabel, *namelabel, *latentry, *lonentry, *altentry, *altlabel, *nameentry=NULL, *commentlabel,
209 *commententry, *imagelabel, *imageentry, *symbollabel, *symbolentry;
212 gchar *lat, *lon, *alt;
214 vik_coord_to_latlon ( &(wp->coord), &ll );
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 );
223 case VIK_UNITS_HEIGHT_FEET:
224 alt = g_strdup_printf ( "%f", VIK_METERS_TO_FEET(wp->altitude) );
227 alt = g_strdup_printf ( "%f", wp->altitude );
228 g_critical("Houston, we've had a problem. height=%d", height_units);
233 namelabel = gtk_label_new (_("Name:"));
234 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), namelabel, FALSE, FALSE, 0);
237 // New waypoint, so name is still changeable
238 nameentry = gtk_entry_new ();
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) );
244 // Existing waypoint - so can not change the name this way - but at least can see it
246 nameentry = gtk_label_new ( default_name );
249 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), nameentry, FALSE, FALSE, 0);
251 latlabel = gtk_label_new (_("Latitude:"));
252 latentry = gtk_entry_new ();
253 gtk_entry_set_text ( GTK_ENTRY(latentry), lat );
256 lonlabel = gtk_label_new (_("Longitude:"));
257 lonentry = gtk_entry_new ();
258 gtk_entry_set_text ( GTK_ENTRY(lonentry), lon );
261 altlabel = gtk_label_new (_("Altitude:"));
262 altentry = gtk_entry_new ();
263 gtk_entry_set_text ( GTK_ENTRY(altentry), alt );
266 commentlabel = gtk_label_new (_("Comment:"));
267 commententry = gtk_entry_new ();
269 cmt = a_vik_goto_get_search_string_for_this_place(VIK_WINDOW(parent));
271 gtk_entry_set_text(GTK_ENTRY(commententry), cmt);
273 imagelabel = gtk_label_new (_("Image:"));
274 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
278 symbollabel = gtk_label_new (_("Symbol:"));
281 store = gtk_list_store_new(3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING);
282 symbolentry = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
283 gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(symbolentry), 6);
285 g_signal_connect(symbolentry, "changed", G_CALLBACK(symbol_entry_changed_cb), store);
286 gtk_list_store_append (store, &iter);
287 gtk_list_store_set (store, &iter, 0, NULL, 1, NULL, 2, _("(none)"), -1);
288 a_populate_sym_list(store);
290 r = gtk_cell_renderer_pixbuf_new ();
291 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (symbolentry), r, FALSE);
292 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (symbolentry), r, "pixbuf", 1, NULL);
294 r = gtk_cell_renderer_text_new ();
295 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (symbolentry), r, FALSE);
296 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (symbolentry), r, "text", 2, NULL);
298 if ( !is_new && wp->symbol ) {
301 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)) {
302 gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
303 if (sym && !strcmp(sym, wp->symbol)) {
310 // Ensure is it a valid symbol in the given symbol set (large vs small)
311 // Not all symbols are available in both
312 // The check prevents a Gtk Critical message
314 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(symbolentry), &iter);
318 if ( !is_new && wp->comment )
319 gtk_entry_set_text ( GTK_ENTRY(commententry), wp->comment );
321 if ( !is_new && wp->image )
322 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), wp->image );
325 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latlabel, FALSE, FALSE, 0);
326 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), latentry, FALSE, FALSE, 0);
327 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonlabel, FALSE, FALSE, 0);
328 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), lonentry, FALSE, FALSE, 0);
329 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), altlabel, FALSE, FALSE, 0);
330 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), altentry, FALSE, FALSE, 0);
331 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), commentlabel, FALSE, FALSE, 0);
332 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), commententry, FALSE, FALSE, 0);
333 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), imagelabel, FALSE, FALSE, 0);
334 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), imageentry, FALSE, FALSE, 0);
335 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), symbollabel, FALSE, FALSE, 0);
336 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(symbolentry), FALSE, FALSE, 0);
338 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
340 gtk_widget_show_all ( GTK_DIALOG(dialog)->vbox );
342 while ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
346 const gchar *entered_name = gtk_entry_get_text ( GTK_ENTRY(nameentry) );
347 if ( strlen(entered_name) == 0 ) /* TODO: other checks (isalpha or whatever ) */
348 a_dialog_info_msg ( parent, _("Please enter a name for the waypoint.") );
351 gchar *use_name = g_strdup ( entered_name );
353 if ( g_hash_table_lookup ( waypoints, use_name ) && !a_dialog_yes_or_no ( parent, _("The waypoint \"%s\" exists, do you want to overwrite it?"), use_name ) )
358 ll.lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
359 ll.lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
360 vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
361 // Always store in metres
362 switch (height_units) {
363 case VIK_UNITS_HEIGHT_METRES:
364 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
366 case VIK_UNITS_HEIGHT_FEET:
367 wp->altitude = VIK_FEET_TO_METERS(atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) ));
370 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
371 g_critical("Houston, we've had a problem. height=%d", height_units);
373 vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
374 vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
375 if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
376 a_thumbnails_create ( wp->image );
379 GtkTreeIter iter, first;
380 gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &first );
381 if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX(symbolentry), &iter ) || !memcmp(&iter, &first, sizeof(GtkTreeIter)) ) {
382 vik_waypoint_set_symbol ( wp, NULL );
385 gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
386 vik_waypoint_set_symbol ( wp, sym );
391 gtk_widget_destroy ( dialog );
394 } /* else (valid name) */
398 ll.lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
399 ll.lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
400 vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
401 switch (height_units) {
402 case VIK_UNITS_HEIGHT_METRES:
403 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
405 case VIK_UNITS_HEIGHT_FEET:
406 wp->altitude = VIK_FEET_TO_METERS(atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) ));
409 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
410 g_critical("Houston, we've had a problem. height=%d", height_units);
412 if ( (! wp->comment) || strcmp ( wp->comment, gtk_entry_get_text ( GTK_ENTRY(commententry) ) ) != 0 )
413 vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
414 if ( (! wp->image) || strcmp ( wp->image, vik_file_entry_get_filename ( VIK_FILE_ENTRY ( imageentry ) ) ) != 0 )
416 vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
417 if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
418 a_thumbnails_create ( wp->image );
422 GtkTreeIter iter, first;
423 gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &first );
424 if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX(symbolentry), &iter ) || !memcmp(&iter, &first, sizeof(GtkTreeIter)) ) {
425 vik_waypoint_set_symbol ( wp, NULL );
428 gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
429 vik_waypoint_set_symbol ( wp, sym );
434 gtk_widget_destroy ( dialog );
440 gtk_widget_destroy ( dialog );
444 static void get_selected_foreach_func(GtkTreeModel *model,
451 gtk_tree_model_get (model, iter, 0, &name, -1);
452 *list = g_list_prepend(*list, name);
455 GList *a_dialog_select_from_list ( GtkWindow *parent, GList *names, gboolean multiple_selection_allowed, const gchar *title, const gchar *msg )
458 GtkCellRenderer *renderer;
461 GtkWidget *dialog = gtk_dialog_new_with_buttons (title,
463 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
469 /* When something is selected then OK */
470 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
471 GtkWidget *response_w = NULL;
472 #if GTK_CHECK_VERSION (2, 20, 0)
473 /* Default to not apply - as initially nothing is selected! */
474 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
476 GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING);
478 GtkWidget *scrolledwindow;
480 GList *runner = names;
483 gtk_list_store_append(store, &iter);
484 gtk_list_store_set(store, &iter, 0, runner->data, -1);
485 runner = g_list_next(runner);
488 view = gtk_tree_view_new();
489 renderer = gtk_cell_renderer_text_new();
490 // Use the column header to display the message text,
491 // this makes the overall widget allocation simple as treeview takes up all the space
492 gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(view), -1, msg, renderer, "text", 0, NULL);
493 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
494 gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(view), TRUE);
495 gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
496 multiple_selection_allowed ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE );
497 g_object_unref(store);
499 scrolledwindow = gtk_scrolled_window_new ( NULL, NULL );
500 gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
501 gtk_container_add ( GTK_CONTAINER(scrolledwindow), view );
503 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolledwindow, TRUE, TRUE, 0 );
504 // Ensure a reasonable number of items are shown, but let the width be automatically sized
505 gtk_widget_set_size_request ( dialog, -1, 400) ;
507 gtk_widget_show_all ( dialog );
510 gtk_widget_grab_focus ( response_w );
512 while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT )
515 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
516 gtk_tree_selection_selected_foreach(selection, get_selected_foreach_func, &names);
519 gtk_widget_destroy ( dialog );
522 a_dialog_error_msg(parent, _("Nothing was selected"));
524 gtk_widget_destroy ( dialog );
528 gchar *a_dialog_new_track ( GtkWindow *parent, GHashTable *tracks, gchar *default_name )
530 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Add Track"),
532 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
538 GtkWidget *label = gtk_label_new ( _("Track Name:") );
539 GtkWidget *entry = gtk_entry_new ();
542 gtk_entry_set_text ( GTK_ENTRY(entry), default_name );
544 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0);
545 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, FALSE, FALSE, 0);
547 g_signal_connect_swapped ( entry, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
549 gtk_widget_show ( label );
550 gtk_widget_show ( entry );
552 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
554 while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT )
556 const gchar *constname = gtk_entry_get_text ( GTK_ENTRY(entry) );
557 if ( *constname == '\0' )
558 a_dialog_info_msg ( parent, _("Please enter a name for the track.") );
560 gchar *name = g_strdup ( constname );
562 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 gtk_widget_destroy ( dialog );
573 gtk_widget_destroy ( dialog );
577 /* creates a vbox full of labels */
578 GtkWidget *a_dialog_create_label_vbox ( gchar **texts, int label_count )
580 GtkWidget *vbox, *label;
582 vbox = gtk_vbox_new( TRUE, 3 );
584 for ( i = 0; i < label_count; i++ )
586 label = gtk_label_new(NULL);
587 gtk_label_set_markup ( GTK_LABEL(label), _(texts[i]) );
588 gtk_box_pack_start ( GTK_BOX(vbox), label, FALSE, TRUE, 5 );
593 gboolean a_dialog_yes_or_no ( GtkWindow *parent, const gchar *message, const gchar *extra )
596 dia = gtk_message_dialog_new ( parent,
597 GTK_DIALOG_DESTROY_WITH_PARENT,
598 GTK_MESSAGE_QUESTION,
602 if ( gtk_dialog_run ( GTK_DIALOG(dia) ) == GTK_RESPONSE_YES )
604 gtk_widget_destroy ( dia );
609 gtk_widget_destroy ( dia );
614 static void zoom_spin_changed ( GtkSpinButton *spin, GtkWidget *pass_along[3] )
616 if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(pass_along[2]) ) )
617 gtk_spin_button_set_value (
618 GTK_SPIN_BUTTON(pass_along[GTK_WIDGET(spin) == pass_along[0] ? 1 : 0]),
619 gtk_spin_button_get_value ( spin ) );
622 gboolean a_dialog_custom_zoom ( GtkWindow *parent, gdouble *xmpp, gdouble *ympp )
624 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Zoom Factors..."),
626 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
632 GtkWidget *table, *label, *xlabel, *xspin, *ylabel, *yspin, *samecheck;
633 GtkWidget *pass_along[3];
635 table = gtk_table_new ( 4, 2, FALSE );
636 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
638 label = gtk_label_new ( _("Zoom factor (in meters per pixel):") );
639 xlabel = gtk_label_new ( _("X (easting): "));
640 ylabel = gtk_label_new ( _("Y (northing): "));
642 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 );
643 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 );
645 pass_along[2] = samecheck = gtk_check_button_new_with_label ( _("X and Y zoom factors must be equal") );
646 /* TODO -- same factor */
647 /* samecheck = gtk_check_button_new_with_label ( "Same x/y zoom factor" ); */
649 if ( *xmpp == *ympp )
650 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(samecheck), TRUE );
652 gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 2, 0, 1 );
653 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 1, 2 );
654 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 1, 2 );
655 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 2, 3 );
656 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 2, 3 );
657 gtk_table_attach_defaults ( GTK_TABLE(table), samecheck, 0, 2, 3, 4 );
659 gtk_widget_show_all ( table );
661 g_signal_connect ( G_OBJECT(xspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
662 g_signal_connect ( G_OBJECT(yspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
664 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
666 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
668 *xmpp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
669 *ympp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
670 gtk_widget_destroy ( dialog );
673 gtk_widget_destroy ( dialog );
677 static void split_spin_focused ( GtkSpinButton *spin, GtkWidget *pass_along[1] )
679 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(pass_along[0]), 1);
682 gboolean a_dialog_time_threshold ( GtkWindow *parent, gchar *title_text, gchar *label_text, guint *thr )
684 GtkWidget *dialog = gtk_dialog_new_with_buttons (title_text,
686 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
692 GtkWidget *table, *t1, *t2, *t3, *t4, *spin, *label;
693 GtkWidget *pass_along[1];
695 table = gtk_table_new ( 4, 2, FALSE );
696 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
698 label = gtk_label_new (label_text);
700 t1 = gtk_radio_button_new_with_label ( NULL, _("1 min") );
701 t2 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t1), _("1 hour") );
702 t3 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t2), _("1 day") );
703 t4 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t3), _("Custom (in minutes):") );
707 spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( *thr, 0, 65536, 1, 5, 0 ), 1, 0 );
709 gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 2, 0, 1 );
710 gtk_table_attach_defaults ( GTK_TABLE(table), t1, 0, 1, 1, 2 );
711 gtk_table_attach_defaults ( GTK_TABLE(table), t2, 0, 1, 2, 3 );
712 gtk_table_attach_defaults ( GTK_TABLE(table), t3, 0, 1, 3, 4 );
713 gtk_table_attach_defaults ( GTK_TABLE(table), t4, 0, 1, 4, 5 );
714 gtk_table_attach_defaults ( GTK_TABLE(table), spin, 1, 2, 4, 5 );
716 gtk_widget_show_all ( table );
718 g_signal_connect ( G_OBJECT(spin), "grab-focus", G_CALLBACK(split_spin_focused), pass_along );
720 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
722 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
724 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t1))) {
726 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t2))) {
728 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t3))) {
730 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t4))) {
731 *thr = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(spin) );
733 gtk_widget_destroy ( dialog );
736 gtk_widget_destroy ( dialog );
741 * Dialog to return a positive number via a spinbox within the supplied limits
742 * A return value of zero indicates the dialog was cancelled
744 guint a_dialog_get_positive_number ( GtkWindow *parent, gchar *title_text, gchar *label_text, guint default_num, guint min, guint max, guint step )
746 GtkWidget *dialog = gtk_dialog_new_with_buttons (title_text,
748 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
754 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
755 GtkWidget *response_w = NULL;
756 #if GTK_CHECK_VERSION (2, 20, 0)
757 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
760 GtkWidget *table, *spin, *label;
761 guint result = default_num;
763 table = gtk_table_new ( 2, 1, FALSE );
764 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
766 label = gtk_label_new (label_text);
767 spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( default_num, min, max, step, 5, 0 ), 1, 0 );
769 gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 1, 0, 1 );
770 gtk_table_attach_defaults ( GTK_TABLE(table), spin, 0, 1, 1, 2 );
773 gtk_widget_grab_focus ( response_w );
775 gtk_widget_show_all ( table );
777 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
779 result = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(spin) );
780 gtk_widget_destroy ( dialog );
785 gtk_widget_destroy ( dialog );
789 static void about_url_hook (GtkAboutDialog *about,
793 open_url (GTK_WINDOW(about), link);
796 static void about_email_hook (GtkAboutDialog *about,
800 new_email (GTK_WINDOW(about), email);
803 void a_dialog_about ( GtkWindow *parent )
805 const gchar *program_name = PACKAGE_NAME;
806 const gchar *version = VIKING_VERSION;
807 const gchar *website = VIKING_URL;
808 const gchar *copyright = "2003-2008, Evan Battaglia\n2008-2010, Viking's contributors";
809 const gchar *comments = _("GPS Data and Topo Analyzer, Explorer, and Manager.");
810 const gchar *license = _("This program is free software; you can redistribute it and/or modify "
811 "it under the terms of the GNU General Public License as published by "
812 "the Free Software Foundation; either version 2 of the License, or "
813 "(at your option) any later version."
815 "This program is distributed in the hope that it will be useful, "
816 "but WITHOUT ANY WARRANTY; without even the implied warranty of "
817 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
818 "GNU General Public License for more details."
820 "You should have received a copy of the GNU General Public License "
821 "along with this program; if not, write to the Free Software "
822 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA");
824 gtk_about_dialog_set_url_hook (about_url_hook, NULL, NULL);
825 gtk_about_dialog_set_email_hook (about_email_hook, NULL, NULL);
826 gtk_show_about_dialog (parent,
827 /* TODO do not set program-name and correctly set info for g_get_application_name */
828 "program-name", program_name,
831 "comments", comments,
832 "copyright", copyright,
834 "wrap-license", TRUE,
835 /* logo automatically retrieved via gtk_window_get_default_icon_list */
837 "documenters", DOCUMENTERS,
838 "translator-credits", _("Translation is coordinated on http://launchpad.net/viking"),
842 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)
846 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 );
847 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
848 GtkWidget *response_w = NULL;
849 #if GTK_CHECK_VERSION (2, 20, 0)
850 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
852 GtkWidget *map_label = gtk_label_new(_("Map type:"));
853 GtkComboBox *map_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
854 for (s = mapnames; *s; s++)
855 gtk_combo_box_append_text(map_combo, *s);
856 gtk_combo_box_set_active (map_combo, default_map);
857 GtkWidget *zoom_label = gtk_label_new(_("Zoom level:"));
858 GtkComboBox *zoom_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
859 for (s = zoom_list; *s; s++)
860 gtk_combo_box_append_text(zoom_combo, *s);
861 gtk_combo_box_set_active (zoom_combo, default_zoom);
863 GtkTable *box = GTK_TABLE(gtk_table_new(2, 2, FALSE));
864 gtk_table_attach_defaults(box, GTK_WIDGET(map_label), 0, 1, 0, 1);
865 gtk_table_attach_defaults(box, GTK_WIDGET(map_combo), 1, 2, 0, 1);
866 gtk_table_attach_defaults(box, GTK_WIDGET(zoom_label), 0, 1, 1, 2);
867 gtk_table_attach_defaults(box, GTK_WIDGET(zoom_combo), 1, 2, 1, 2);
869 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
872 gtk_widget_grab_focus ( response_w );
874 gtk_widget_show_all ( dialog );
875 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
876 gtk_widget_destroy(dialog);
880 *selected_map = gtk_combo_box_get_active(map_combo);
881 *selected_zoom = gtk_combo_box_get_active(zoom_combo);
883 gtk_widget_destroy(dialog);
888 * Display a dialog presenting the license of a map.
889 * Allow to read the license by launching a web browser.
891 void a_dialog_license ( GtkWindow *parent, const gchar *map, const gchar *license, const gchar *url)
893 GtkWidget *dialog = gtk_message_dialog_new (parent,
894 GTK_DIALOG_DESTROY_WITH_PARENT,
897 _("The map data is licensed: %s."),
899 gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
900 _("The data provided by '<b>%s</b>' are licensed under the following license: <b>%s</b>.\n"
901 "Please, read the license before continuing."),
903 #define RESPONSE_OPEN_LICENSE 600
905 gtk_dialog_add_button (GTK_DIALOG (dialog), _("Open license"), RESPONSE_OPEN_LICENSE);
909 response = gtk_dialog_run (GTK_DIALOG (dialog));
910 if (response == RESPONSE_OPEN_LICENSE) {
911 open_url (parent, url);
913 } while (response != GTK_RESPONSE_DELETE_EVENT && response != GTK_RESPONSE_OK);
914 gtk_widget_destroy (dialog);