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, 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;
209 GtkWidget *commentlabel, *commententry, *descriptionlabel, *descriptionentry, *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 // 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));
272 gtk_entry_set_text(GTK_ENTRY(commententry), cmt);
274 descriptionlabel = gtk_label_new (_("Description:"));
275 descriptionentry = gtk_entry_new ();
277 imagelabel = gtk_label_new (_("Image:"));
278 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
282 symbollabel = gtk_label_new (_("Symbol:"));
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);
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);
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);
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);
302 if ( !is_new && wp->symbol ) {
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)) {
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
318 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(symbolentry), &iter);
322 if ( !is_new && wp->comment )
323 gtk_entry_set_text ( GTK_ENTRY(commententry), wp->comment );
325 if ( !is_new && wp->description )
326 gtk_entry_set_text ( GTK_ENTRY(descriptionentry), wp->description );
328 if ( !is_new && wp->image )
329 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), wp->image );
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);
347 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
349 gtk_widget_show_all ( GTK_DIALOG(dialog)->vbox );
351 while ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
355 if ( strlen((gchar*)gtk_entry_get_text ( GTK_ENTRY(nameentry) )) == 0 ) /* TODO: other checks (isalpha or whatever ) */
356 a_dialog_info_msg ( parent, _("Please enter a name for the waypoint.") );
358 // NB: No check for unique names - this allows generation of same named entries.
359 gchar *entered_name = g_strdup ( (gchar*)gtk_entry_get_text ( GTK_ENTRY(nameentry) ) );
362 ll.lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
363 ll.lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
364 vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
365 // Always store in metres
366 switch (height_units) {
367 case VIK_UNITS_HEIGHT_METRES:
368 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
370 case VIK_UNITS_HEIGHT_FEET:
371 wp->altitude = VIK_FEET_TO_METERS(atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) ));
374 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
375 g_critical("Houston, we've had a problem. height=%d", height_units);
377 vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
378 vik_waypoint_set_description ( wp, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) );
379 vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
380 if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
381 a_thumbnails_create ( wp->image );
383 GtkTreeIter iter, first;
384 gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &first );
385 if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX(symbolentry), &iter ) || !memcmp(&iter, &first, sizeof(GtkTreeIter)) ) {
386 vik_waypoint_set_symbol ( wp, NULL );
389 gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
390 vik_waypoint_set_symbol ( wp, sym );
394 gtk_widget_destroy ( dialog );
400 ll.lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
401 ll.lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
402 vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
403 switch (height_units) {
404 case VIK_UNITS_HEIGHT_METRES:
405 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
407 case VIK_UNITS_HEIGHT_FEET:
408 wp->altitude = VIK_FEET_TO_METERS(atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) ));
411 wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
412 g_critical("Houston, we've had a problem. height=%d", height_units);
414 if ( (! wp->comment) || strcmp ( wp->comment, gtk_entry_get_text ( GTK_ENTRY(commententry) ) ) != 0 )
415 vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
416 if ( (! wp->description) || strcmp ( wp->description, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) ) != 0 )
417 vik_waypoint_set_description ( wp, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) );
418 if ( (! wp->image) || strcmp ( wp->image, vik_file_entry_get_filename ( VIK_FILE_ENTRY ( imageentry ) ) ) != 0 )
420 vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
421 if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
422 a_thumbnails_create ( wp->image );
426 GtkTreeIter iter, first;
427 gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &first );
428 if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX(symbolentry), &iter ) || !memcmp(&iter, &first, sizeof(GtkTreeIter)) ) {
429 vik_waypoint_set_symbol ( wp, NULL );
432 gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
433 vik_waypoint_set_symbol ( wp, sym );
438 gtk_widget_destroy ( dialog );
444 gtk_widget_destroy ( dialog );
448 static void get_selected_foreach_func(GtkTreeModel *model,
455 gtk_tree_model_get (model, iter, 0, &name, -1);
456 *list = g_list_prepend(*list, name);
459 GList *a_dialog_select_from_list ( GtkWindow *parent, GList *names, gboolean multiple_selection_allowed, const gchar *title, const gchar *msg )
462 GtkCellRenderer *renderer;
465 GtkWidget *dialog = gtk_dialog_new_with_buttons (title,
467 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
473 /* When something is selected then OK */
474 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
475 GtkWidget *response_w = NULL;
476 #if GTK_CHECK_VERSION (2, 20, 0)
477 /* Default to not apply - as initially nothing is selected! */
478 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
480 GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING);
482 GtkWidget *scrolledwindow;
484 GList *runner = names;
487 gtk_list_store_append(store, &iter);
488 gtk_list_store_set(store, &iter, 0, runner->data, -1);
489 runner = g_list_next(runner);
492 view = gtk_tree_view_new();
493 renderer = gtk_cell_renderer_text_new();
494 // Use the column header to display the message text,
495 // this makes the overall widget allocation simple as treeview takes up all the space
496 GtkTreeViewColumn *column;
497 column = gtk_tree_view_column_new_with_attributes (msg, renderer, "text", 0, NULL );
498 gtk_tree_view_column_set_sort_column_id (column, 0);
499 gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
501 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
502 gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
503 multiple_selection_allowed ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE );
504 g_object_unref(store);
506 scrolledwindow = gtk_scrolled_window_new ( NULL, NULL );
507 gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
508 gtk_container_add ( GTK_CONTAINER(scrolledwindow), view );
510 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolledwindow, TRUE, TRUE, 0 );
511 // Ensure a reasonable number of items are shown, but let the width be automatically sized
512 gtk_widget_set_size_request ( dialog, -1, 400) ;
514 gtk_widget_show_all ( dialog );
517 gtk_widget_grab_focus ( response_w );
519 while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT )
522 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
523 gtk_tree_selection_selected_foreach(selection, get_selected_foreach_func, &names);
526 gtk_widget_destroy ( dialog );
529 a_dialog_error_msg(parent, _("Nothing was selected"));
531 gtk_widget_destroy ( dialog );
535 gchar *a_dialog_new_track ( GtkWindow *parent, GHashTable *tracks, gchar *default_name, gboolean is_route )
537 GtkWidget *dialog = gtk_dialog_new_with_buttons ( is_route ? _("Add Route") : _("Add Track"),
539 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
545 GtkWidget *label = gtk_label_new ( is_route ? _("Route Name:") : _("Track Name:") );
546 GtkWidget *entry = gtk_entry_new ();
549 gtk_entry_set_text ( GTK_ENTRY(entry), default_name );
551 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0);
552 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, FALSE, FALSE, 0);
554 g_signal_connect_swapped ( entry, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
556 gtk_widget_show ( label );
557 gtk_widget_show ( entry );
559 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
561 while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT )
563 const gchar *constname = gtk_entry_get_text ( GTK_ENTRY(entry) );
564 if ( *constname == '\0' )
565 a_dialog_info_msg ( parent, _("Please enter a name for the track.") );
567 gchar *name = g_strdup ( constname );
568 gtk_widget_destroy ( dialog );
572 gtk_widget_destroy ( dialog );
576 /* creates a vbox full of labels */
577 GtkWidget *a_dialog_create_label_vbox ( gchar **texts, int label_count )
579 GtkWidget *vbox, *label;
581 vbox = gtk_vbox_new( TRUE, 3 );
583 for ( i = 0; i < label_count; i++ )
585 label = gtk_label_new(NULL);
586 gtk_label_set_markup ( GTK_LABEL(label), _(texts[i]) );
587 gtk_box_pack_start ( GTK_BOX(vbox), label, FALSE, TRUE, 5 );
592 gboolean a_dialog_yes_or_no ( GtkWindow *parent, const gchar *message, const gchar *extra )
595 dia = gtk_message_dialog_new ( parent,
596 GTK_DIALOG_DESTROY_WITH_PARENT,
597 GTK_MESSAGE_QUESTION,
601 if ( gtk_dialog_run ( GTK_DIALOG(dia) ) == GTK_RESPONSE_YES )
603 gtk_widget_destroy ( dia );
608 gtk_widget_destroy ( dia );
613 static void zoom_spin_changed ( GtkSpinButton *spin, GtkWidget *pass_along[3] )
615 if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(pass_along[2]) ) )
616 gtk_spin_button_set_value (
617 GTK_SPIN_BUTTON(pass_along[GTK_WIDGET(spin) == pass_along[0] ? 1 : 0]),
618 gtk_spin_button_get_value ( spin ) );
621 gboolean a_dialog_custom_zoom ( GtkWindow *parent, gdouble *xmpp, gdouble *ympp )
623 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Zoom Factors..."),
625 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
631 GtkWidget *table, *label, *xlabel, *xspin, *ylabel, *yspin, *samecheck;
632 GtkWidget *pass_along[3];
634 table = gtk_table_new ( 4, 2, FALSE );
635 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
637 label = gtk_label_new ( _("Zoom factor (in meters per pixel):") );
638 xlabel = gtk_label_new ( _("X (easting): "));
639 ylabel = gtk_label_new ( _("Y (northing): "));
641 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 );
642 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 );
644 pass_along[2] = samecheck = gtk_check_button_new_with_label ( _("X and Y zoom factors must be equal") );
645 /* TODO -- same factor */
646 /* samecheck = gtk_check_button_new_with_label ( "Same x/y zoom factor" ); */
648 if ( *xmpp == *ympp )
649 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(samecheck), TRUE );
651 gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 2, 0, 1 );
652 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 1, 2 );
653 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 1, 2 );
654 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 2, 3 );
655 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 2, 3 );
656 gtk_table_attach_defaults ( GTK_TABLE(table), samecheck, 0, 2, 3, 4 );
658 gtk_widget_show_all ( table );
660 g_signal_connect ( G_OBJECT(xspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
661 g_signal_connect ( G_OBJECT(yspin), "value-changed", G_CALLBACK(zoom_spin_changed), pass_along );
663 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
665 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
667 *xmpp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
668 *ympp = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
669 gtk_widget_destroy ( dialog );
672 gtk_widget_destroy ( dialog );
676 static void split_spin_focused ( GtkSpinButton *spin, GtkWidget *pass_along[1] )
678 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(pass_along[0]), 1);
681 gboolean a_dialog_time_threshold ( GtkWindow *parent, gchar *title_text, gchar *label_text, guint *thr )
683 GtkWidget *dialog = gtk_dialog_new_with_buttons (title_text,
685 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
691 GtkWidget *table, *t1, *t2, *t3, *t4, *spin, *label;
692 GtkWidget *pass_along[1];
694 table = gtk_table_new ( 4, 2, FALSE );
695 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
697 label = gtk_label_new (label_text);
699 t1 = gtk_radio_button_new_with_label ( NULL, _("1 min") );
700 t2 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t1), _("1 hour") );
701 t3 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t2), _("1 day") );
702 t4 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(t3), _("Custom (in minutes):") );
706 spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( *thr, 0, 65536, 1, 5, 0 ), 1, 0 );
708 gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 2, 0, 1 );
709 gtk_table_attach_defaults ( GTK_TABLE(table), t1, 0, 1, 1, 2 );
710 gtk_table_attach_defaults ( GTK_TABLE(table), t2, 0, 1, 2, 3 );
711 gtk_table_attach_defaults ( GTK_TABLE(table), t3, 0, 1, 3, 4 );
712 gtk_table_attach_defaults ( GTK_TABLE(table), t4, 0, 1, 4, 5 );
713 gtk_table_attach_defaults ( GTK_TABLE(table), spin, 1, 2, 4, 5 );
715 gtk_widget_show_all ( table );
717 g_signal_connect ( G_OBJECT(spin), "grab-focus", G_CALLBACK(split_spin_focused), pass_along );
719 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
721 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
723 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t1))) {
725 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t2))) {
727 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t3))) {
729 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t4))) {
730 *thr = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(spin) );
732 gtk_widget_destroy ( dialog );
735 gtk_widget_destroy ( dialog );
740 * Dialog to return a positive number via a spinbox within the supplied limits
741 * A return value of zero indicates the dialog was cancelled
743 guint a_dialog_get_positive_number ( GtkWindow *parent, gchar *title_text, gchar *label_text, guint default_num, guint min, guint max, guint step )
745 GtkWidget *dialog = gtk_dialog_new_with_buttons (title_text,
747 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
753 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
754 GtkWidget *response_w = NULL;
755 #if GTK_CHECK_VERSION (2, 20, 0)
756 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
759 GtkWidget *table, *spin, *label;
760 guint result = default_num;
762 table = gtk_table_new ( 2, 1, FALSE );
763 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
765 label = gtk_label_new (label_text);
766 spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( default_num, min, max, step, 5, 0 ), 1, 0 );
768 gtk_table_attach_defaults ( GTK_TABLE(table), label, 0, 1, 0, 1 );
769 gtk_table_attach_defaults ( GTK_TABLE(table), spin, 0, 1, 1, 2 );
772 gtk_widget_grab_focus ( response_w );
774 gtk_widget_show_all ( table );
776 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
778 result = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(spin) );
779 gtk_widget_destroy ( dialog );
784 gtk_widget_destroy ( dialog );
788 static void about_url_hook (GtkAboutDialog *about,
792 open_url (GTK_WINDOW(about), link);
795 static void about_email_hook (GtkAboutDialog *about,
799 new_email (GTK_WINDOW(about), email);
802 void a_dialog_about ( GtkWindow *parent )
804 const gchar *program_name = PACKAGE_NAME;
805 const gchar *version = VIKING_VERSION;
806 const gchar *website = VIKING_URL;
807 const gchar *copyright = "2003-2008, Evan Battaglia\n2008-2010, Viking's contributors";
808 const gchar *comments = _("GPS Data and Topo Analyzer, Explorer, and Manager.");
809 const gchar *license = _("This program is free software; you can redistribute it and/or modify "
810 "it under the terms of the GNU General Public License as published by "
811 "the Free Software Foundation; either version 2 of the License, or "
812 "(at your option) any later version."
814 "This program is distributed in the hope that it will be useful, "
815 "but WITHOUT ANY WARRANTY; without even the implied warranty of "
816 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
817 "GNU General Public License for more details."
819 "You should have received a copy of the GNU General Public License "
820 "along with this program; if not, write to the Free Software "
821 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA");
823 gtk_about_dialog_set_url_hook (about_url_hook, NULL, NULL);
824 gtk_about_dialog_set_email_hook (about_email_hook, NULL, NULL);
825 gtk_show_about_dialog (parent,
826 /* TODO do not set program-name and correctly set info for g_get_application_name */
827 "program-name", program_name,
830 "comments", comments,
831 "copyright", copyright,
833 "wrap-license", TRUE,
834 /* logo automatically retrieved via gtk_window_get_default_icon_list */
836 "documenters", DOCUMENTERS,
837 "translator-credits", _("Translation is coordinated on http://launchpad.net/viking"),
841 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)
845 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 );
846 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
847 GtkWidget *response_w = NULL;
848 #if GTK_CHECK_VERSION (2, 20, 0)
849 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
851 GtkWidget *map_label = gtk_label_new(_("Map type:"));
852 GtkComboBox *map_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
853 for (s = mapnames; *s; s++)
854 gtk_combo_box_append_text(map_combo, *s);
855 gtk_combo_box_set_active (map_combo, default_map);
856 GtkWidget *zoom_label = gtk_label_new(_("Zoom level:"));
857 GtkComboBox *zoom_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
858 for (s = zoom_list; *s; s++)
859 gtk_combo_box_append_text(zoom_combo, *s);
860 gtk_combo_box_set_active (zoom_combo, default_zoom);
862 GtkTable *box = GTK_TABLE(gtk_table_new(2, 2, FALSE));
863 gtk_table_attach_defaults(box, GTK_WIDGET(map_label), 0, 1, 0, 1);
864 gtk_table_attach_defaults(box, GTK_WIDGET(map_combo), 1, 2, 0, 1);
865 gtk_table_attach_defaults(box, GTK_WIDGET(zoom_label), 0, 1, 1, 2);
866 gtk_table_attach_defaults(box, GTK_WIDGET(zoom_combo), 1, 2, 1, 2);
868 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
871 gtk_widget_grab_focus ( response_w );
873 gtk_widget_show_all ( dialog );
874 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
875 gtk_widget_destroy(dialog);
879 *selected_map = gtk_combo_box_get_active(map_combo);
880 *selected_zoom = gtk_combo_box_get_active(zoom_combo);
882 gtk_widget_destroy(dialog);
887 * Display a dialog presenting the license of a map.
888 * Allow to read the license by launching a web browser.
890 void a_dialog_license ( GtkWindow *parent, const gchar *map, const gchar *license, const gchar *url)
892 GtkWidget *dialog = gtk_message_dialog_new (parent,
893 GTK_DIALOG_DESTROY_WITH_PARENT,
896 _("The map data is licensed: %s."),
898 gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
899 _("The data provided by '<b>%s</b>' are licensed under the following license: <b>%s</b>.\n"
900 "Please, read the license before continuing."),
902 #define RESPONSE_OPEN_LICENSE 600
904 gtk_dialog_add_button (GTK_DIALOG (dialog), _("Open license"), RESPONSE_OPEN_LICENSE);
908 response = gtk_dialog_run (GTK_DIALOG (dialog));
909 if (response == RESPONSE_OPEN_LICENSE) {
910 open_url (parent, url);
912 } while (response != GTK_RESPONSE_DELETE_EVENT && response != GTK_RESPONSE_OK);
913 gtk_widget_destroy (dialog);