]> err.no Git - mapper/blob - src/cb.c
1bcef4fff3d936defcd7aab2d49ea79447c77dca
[mapper] / src / cb.c
1 /*
2  * This file is part of mapper
3  *
4  * Copyright (C) 2007 Kaj-Michael Lang
5  * Copyright (C) 2006-2007 John Costigan.
6  *
7  * POI and GPS-Info code originally written by Cezary Jackiewicz.
8  *
9  * Default map data provided by http://www.openstreetmap.org/
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include <config.h>
27
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <stddef.h>
33 #include <locale.h>
34 #include <errno.h>
35 #include <sys/wait.h>
36 #include <glib/gstdio.h>
37 #include <gtk/gtk.h>
38 #include <gdk/gdkkeysyms.h>
39 #include <fcntl.h>
40 #include <libintl.h>
41 #include <locale.h>
42
43 #include "hildon-mapper.h"
44
45 #include "utils.h"
46 #include "poi.h"
47 #include "path.h"
48 #include "settings.h"
49 #include "gps.h"
50 #include "mapper-types.h"
51 #include "ui-common.h"
52 #include "db.h"
53 #include "latlon.h"
54 #include "cb.h"
55 #include "poi-gui.h"
56 #include "gps-panels.h"
57 #include "gps-conn.h"
58 #include "search.h"
59 #include "dialogs.h"
60 #include "filter-gui.h"
61 #include "help.h"
62 #include "map-repo-manager.h"
63 #include "config-gconf.h"
64 #include "gtkmap.h"
65
66 static gboolean
67 path_tree_view_update_store(GtkWidget *tree_view, Path *path)
68 {
69 GtkListStore *store;
70
71 g_assert(tree_view);
72 g_assert(path);
73
74 store=path_get_waypoints_store(path, _degformat);
75 if (!store)
76         return FALSE;
77
78 gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), store);
79 g_object_unref(G_OBJECT(store));
80 return TRUE;
81 }
82
83 /***********************
84   Route menu callbacks 
85  ***********************/
86 gboolean 
87 menu_cb_route_download(GtkAction *action)
88 {
89 route_download(_route, NULL);
90 route_menu_set_sensitive(path_tree_view_update_store(route_tree_view, _route));
91 return TRUE;
92 }
93
94 gboolean 
95 menu_cb_route_open(GtkAction *action)
96 {
97 route_open_file(_route);
98 route_menu_set_sensitive(path_tree_view_update_store(route_tree_view, _route));
99 return TRUE;
100 }
101
102 gboolean 
103 menu_cb_route_save(GtkAction *action)
104 {
105 route_save(_route);
106 return TRUE;
107 }
108
109 gboolean 
110 menu_cb_route_distnext(GtkAction *action)
111 {
112 path_show_distance_to_next(_route);
113 return TRUE;
114 }
115
116 gboolean 
117 menu_cb_route_distlast(GtkAction *action)
118 {
119 path_show_distance_to_last(_route);
120 return TRUE;
121 }
122
123 gboolean 
124 menu_cb_route_reset(GtkAction *action)
125 {
126 path_find_nearest_point(_route, _gps->data.lat, _gps->data.lon);
127 return TRUE;
128 }
129
130 gboolean 
131 menu_cb_route_clear(GtkAction *action)
132 {
133 if (path_clear_ask(_route), _("Clear route ?")) {
134         gtk_tree_view_set_model(route_tree_view, NULL);
135         route_menu_set_sensitive(FALSE);
136 }
137 return TRUE;
138 }
139
140 /***********************
141   Track menu callbacks 
142  ***********************/
143 gboolean 
144 menu_cb_track_open(GtkAction *action)
145 {
146 track_open(_track);
147 path_tree_view_update_store(track_tree_view, _track);
148 return TRUE;
149 }
150
151 gboolean 
152 menu_cb_track_save(GtkAction *action)
153 {
154 track_save(_track);
155 path_tree_view_update_store(track_tree_view, _track);
156 return TRUE;
157 }
158
159 gboolean 
160 menu_cb_track_insert_break(GtkAction *action)
161 {
162 path_add_break(_track);
163 path_tree_view_update_store(track_tree_view, _track);
164 return TRUE;
165 }
166
167 gboolean 
168 menu_cb_track_insert_mark(GtkAction *action)
169 {
170 if (path_insert_mark_ask(_track))
171         path_tree_view_update_store(track_tree_view, _track);
172 return TRUE;
173 }
174
175 gboolean 
176 menu_cb_track_distlast(GtkAction *action)
177 {
178 path_show_distance_from_last(_track);
179 return TRUE;
180 }
181
182 gboolean 
183 menu_cb_track_distfirst(GtkAction *action)
184 {
185 path_show_distance_from_first(_track);
186 return TRUE;
187 }
188
189 gboolean 
190 menu_cb_track_clear(GtkAction *action)
191 {
192 path_clear(_track);
193 path_tree_view_update_store(track_tree_view, _track);
194 return TRUE;
195 }
196
197 gboolean 
198 menu_cb_track_filter(GtkAction *action)
199 {
200 filter_dialog(_window);
201 return TRUE;
202 }
203
204 /***********************
205   Other menu callbacks 
206  ***********************/
207 gboolean 
208 menu_cb_show_tracks(GtkAction *action)
209 {
210 _show_tracks ^= TRACKS_MASK;
211 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) {
212         _show_tracks |= TRACKS_MASK;
213         gtk_map_set_path_display(_map, _show_tracks);
214         MACRO_BANNER_SHOW_INFO(_window, _("Tracks are now shown"));
215 } else {
216         _show_tracks &= ~TRACKS_MASK;
217         gtk_map_set_path_display(_map, _show_tracks);
218         MACRO_BANNER_SHOW_INFO(_window, _("Tracks are now hidden"));
219 }
220 return TRUE;
221 }
222
223 gboolean 
224 menu_cb_show_scale(GtkAction *action)
225 {
226 _show_scale = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
227 /* XXXXXXXXXXXXXXXXX */
228 return TRUE;
229 }
230
231 gboolean 
232 menu_cb_show_routes(GtkAction *action)
233 {
234 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) {
235         _show_tracks |= ROUTES_MASK;
236         gtk_map_set_path_display(_map, _show_tracks);
237         MACRO_BANNER_SHOW_INFO(_window, _("Routes are now shown"));
238 } else {
239         _show_tracks &= ~ROUTES_MASK;
240         gtk_map_set_path_display(_map, _show_tracks);
241         MACRO_BANNER_SHOW_INFO(_window, _("Routes are now hidden"));
242 }
243 return TRUE;
244 }
245
246 gboolean 
247 menu_cb_show_velvec(GtkAction *action)
248 {
249 _show_velvec = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
250 g_object_set(_map, "show-velvec", _show_velvec, NULL);
251 return TRUE;
252 }
253
254 gboolean 
255 menu_cb_show_poi(GtkAction *action)
256 {
257 _show_poi = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
258 g_object_set(_map, "show-markers", _show_poi, NULL);
259 return TRUE;
260 }
261
262 gboolean 
263 menu_cb_gps_show_info(GtkAction *action)
264 {
265 _gps_info = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
266 gps_show_info(_gps);
267 return TRUE;
268 }
269
270 gboolean
271 menu_cb_autocenter(GtkAction *action, GtkRadioAction *current)
272 {
273 gint value=gtk_radio_action_get_current_value(GTK_RADIO_ACTION(current));
274
275 switch (value) {
276         case CENTER_LEAD:
277                 gtk_map_set_center_mode(_map, CENTER_LEAD);
278                 MACRO_BANNER_SHOW_INFO(_window, _("Auto-Center Mode: Lead"));
279         break;
280         case CENTER_LATLON:
281                 gtk_map_set_center_mode(_map, CENTER_LATLON);
282                 MACRO_BANNER_SHOW_INFO(_window, _("Auto-Center Mode: Lat/Lon"));
283         break;
284         case CENTER_MANUAL:
285         default:
286                 gtk_map_set_center_mode(_map, CENTER_MANUAL);
287                 MACRO_BANNER_SHOW_INFO(_window, _("Auto-Center Off"));
288         break;
289 }
290
291 return TRUE;
292 }
293
294 gboolean 
295 menu_cb_goto_latlon(GtkAction *action)
296 {
297 gtk_map_dialog_goto_latlon();
298 return TRUE;
299 }
300
301 gboolean 
302 menu_cb_goto_home(GtkAction *action)
303 {
304 if (gtk_map_goto_position(_map, _home)==FALSE) {
305         MACRO_BANNER_SHOW_INFO(_window, _("Home not set."));
306 } else {
307         if (gtk_map_get_zoom(_map)>3)
308                 gtk_map_set_zoom(_map, 3);
309         MACRO_BANNER_SHOW_INFO(_window, _("At home location"));
310 }
311 return TRUE;
312 }
313
314 gboolean 
315 menu_cb_goto_destination(GtkAction *action)
316 {
317 if (gtk_map_goto_position(_map, _dest)==FALSE) {
318         MACRO_BANNER_SHOW_INFO(_window, _("Destination has not been set."));
319 } else {
320         if (gtk_map_get_zoom(_map)>3)
321                 gtk_map_set_zoom(_map, 3);
322         MACRO_BANNER_SHOW_INFO(_window, _("At destination point"));
323 }
324 return TRUE;
325 }
326
327 gboolean 
328 menu_cb_goto_gps(GtkAction *action)
329 {
330 if (gtk_map_set_center_mode(_map, CENTER_LATLON)) {
331         MACRO_BANNER_SHOW_INFO(_window, _("At GPS track coordinates."));
332 } else {
333         MACRO_BANNER_SHOW_INFO(_window, _("No active GPS track."));
334 }
335 return TRUE;
336 }
337
338 gboolean 
339 menu_cb_goto_nextway(GtkAction *action)
340 {
341 GtkMapCenterMode cm;
342
343 g_return_val_if_fail(_route, TRUE);
344
345 if (_route->next_way && _route->next_way->point && _route->next_way->point->unity && _route->next_way->point->unitx) {
346         g_object_get(_map, "center-mode", &cm);
347         if (cm>0)
348                 set_action_activate("autocenter_none", TRUE);
349
350         gtk_map_set_center(_map, _route->next_way->point->unitx, _route->next_way->point->unity);
351         if (gtk_map_get_zoom(_map)>3)
352                 gtk_map_set_zoom(_map, 3);
353 } else {
354         MACRO_BANNER_SHOW_INFO(_window, _("There is no next waypoint."));
355 }
356
357 return TRUE;
358 }
359
360 gboolean 
361 menu_cb_goto_nearpoi(GtkAction *action)
362 {
363 GtkMapCenterMode cm;
364 gdouble lat, lon;
365 poi_info *p;
366
367 gtk_map_get_center_latlon(_map, &lat, &lon);
368
369 p=poi_find_nearest(lat, lon);
370 if (p) {
371         gchar *banner;
372
373         banner = g_strdup_printf("%s (%s)", p->label, p->cat_label);
374         MACRO_BANNER_SHOW_INFO(_window, banner);
375         g_free(banner);
376         poi_free(p);
377
378         g_object_get(_map, "center-mode", &cm);
379         if (cm!=CENTER_MANUAL)
380                 set_action_activate("autocenter_none", TRUE);
381
382         gtk_map_set_center_latlon(_map, p->lat, p->lon);
383 } else {
384         MACRO_BANNER_SHOW_INFO(_window, _("No POIs found."));
385 }
386
387 return TRUE;
388 }
389
390 gboolean 
391 menu_cb_maps_repoman(GtkAction *action)
392 {
393 repoman_dialog();
394 return TRUE;
395 }
396
397 gboolean 
398 menu_cb_maps_select(GtkAction *action, gpointer new_repo)
399 {
400 gtk_map_set_repo(_map, new_repo);
401 return TRUE;
402 }
403
404 gboolean 
405 cb_zoom_auto(GtkAction *action)
406 {
407 gtk_map_set_autozoom(_map, TRUE);
408 return TRUE;
409 }
410
411 gboolean 
412 cb_zoom_base(GtkAction *action)
413 {
414 gtk_map_set_autozoom(_map, FALSE);
415 return TRUE;
416 }
417
418 gboolean 
419 cb_zoomin(GtkAction *action)
420 {
421 g_idle_add((GSourceFunc)gtk_map_zoom_in, NULL);
422 return TRUE;
423 }
424
425 gboolean 
426 cb_zoomout(GtkAction *action)
427 {
428 g_idle_add((GSourceFunc)gtk_map_zoom_out, NULL);
429 return TRUE;
430 }
431
432 gboolean 
433 cb_fullscreen(GtkAction *action)
434 {
435 if ((_fullscreen = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))) {
436         gtk_window_fullscreen(GTK_WINDOW(_window));
437 } else {
438         gtk_window_unfullscreen(GTK_WINDOW(_window));
439 }
440 gtk_idle_add((GSourceFunc) window_present, NULL);
441 return TRUE;
442 }
443
444 gboolean
445 menu_cb_view_toolbar(GtkAction *action)
446 {
447 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))
448         gtk_widget_show(_toolbar);
449 else
450         gtk_widget_hide(_toolbar);
451
452 return TRUE;
453 }
454
455 gboolean 
456 menu_cb_enable_gps(GtkAction *action)
457 {
458 if ((_enable_gps = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))) {
459         if (_gps->io.address) {
460                 gps_conn_set_state(_gps, RCVR_DOWN);
461                 gps_connect_now(_gps);
462         } else {
463                 MACRO_BANNER_SHOW_INFO(_window, _("Cannot enable GPS until a GPS Receiver has been configured in the GPS Settings dialog."));
464                 set_action_activate("gps_enabled", FALSE);
465         }
466 } else {
467         if (_gps->io.conn > RCVR_OFF)
468                 gps_conn_set_state(_gps, RCVR_OFF);
469         gps_disconnect(_gps);
470         path_add_break(_track);
471         _speed_excess=FALSE;
472 }
473 if (_enable_gps==FALSE)
474         set_action_activate("autocenter_none", TRUE);
475 set_action_sensitive("goto_gps", _enable_gps);
476 set_action_sensitive("autocenter_latlon", _enable_gps);
477 set_action_sensitive("autocenter_lead", _enable_gps);
478
479 gps_show_info(&_gps->data);
480
481 return TRUE;
482 }
483
484 gboolean 
485 menu_cb_auto_download(GtkAction *action)
486 {
487 if ((_auto_download = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)) )) {
488         if (_curr_repo->url == REPOTYPE_NONE)
489                 popup_error(_window, _("NOTE: You must set a Map URI in the current repository in order to download maps."));
490         gtk_map_refresh(_map);
491 } else {
492         map_download_stop();
493 }
494
495 return TRUE;
496 }
497
498 gboolean 
499 menu_cb_settings(GtkAction *action)
500 {
501 if (settings_dialog()) {
502         gtk_map_refresh(_map);
503 }
504 return TRUE;
505 }
506
507 gboolean 
508 menu_cb_settings_gps(GtkAction *action)
509 {
510 if (settings_dialog_gps(_gps)) {
511         /* Settings have changed - reconnect to receiver. */
512         if (_enable_gps) {
513                 gps_conn_set_state(_gps, RCVR_DOWN);
514                 gps_disconnect(_gps);
515                 gps_connect_now(_gps);
516         }
517 }
518
519 return TRUE;
520 }
521
522 gboolean 
523 menu_cb_settings_colors(GtkAction *action)
524 {
525 settings_dialog_colors();
526 return TRUE;
527 }
528
529 gboolean 
530 menu_cb_settings_osm(GtkAction *action)
531 {
532 settings_dialog_osm();
533 return TRUE;
534 }
535
536 gboolean 
537 menu_cb_settings_keys(GtkAction *action)
538 {
539 settings_dialog_hardkeys();
540 return TRUE;
541 }
542
543 gboolean 
544 menu_cb_import_osm(GtkAction *action)
545 {
546 osm_import_dialog(_window);
547 return TRUE;
548 }
549
550 gboolean 
551 menu_cb_help(GtkAction *action)
552 {
553 help_topic_display(HELP_ID_INTRO, 0);
554 return TRUE;
555 }
556
557 gboolean 
558 menu_cb_about(GtkAction *action)
559 {
560 gchar *authors[]={
561         "Kaj-Michael Lang",
562         "John Costigan",
563         "Cezary Jackiewicz", NULL
564 };
565
566 gtk_show_about_dialog(GTK_WINDOW(_window), 
567         "name", "Mapper",
568         "version", VERSION, 
569         "copyright", "Kaj-Michael Lang",
570         "license", "GPL",
571         "authors", authors,
572         NULL);
573 return TRUE;
574 }
575
576 static CustomKey
577 custom_key_get_type(gint keyval)
578 {
579 switch (keyval) {
580         case HILDON_HARDKEY_UP:
581                 return CUSTOM_KEY_UP;
582         break;
583         case HILDON_HARDKEY_DOWN:
584                 return CUSTOM_KEY_DOWN;
585         break;
586         case HILDON_HARDKEY_LEFT:
587                 return CUSTOM_KEY_LEFT;
588         break;
589         case HILDON_HARDKEY_RIGHT:
590                 return CUSTOM_KEY_RIGHT;
591         break;
592         case HILDON_HARDKEY_SELECT:
593                 return CUSTOM_KEY_SELECT;
594         break;
595         case HILDON_HARDKEY_INCREASE:
596                 return CUSTOM_KEY_INCREASE;
597         break;
598         case HILDON_HARDKEY_DECREASE:
599                 return CUSTOM_KEY_DECREASE;
600         break;
601         case HILDON_HARDKEY_FULLSCREEN:
602                 return CUSTOM_KEY_FULLSCREEN;
603         break;
604         case HILDON_HARDKEY_ESC:
605                 return CUSTOM_KEY_ESC;
606         break;
607         default:
608                 return CUSTOM_KEY_ENUM_COUNT;
609 }
610
611 }
612
613 gboolean 
614 window_cb_key_press(GtkWidget * widget, GdkEventKey * event)
615 {
616 CustomKey custom_key;
617 GtkMapCenterMode cm;
618
619 custom_key=custom_key_get_type(event->keyval);
620 if (custom_key==CUSTOM_KEY_ENUM_COUNT)
621         return FALSE;
622
623 switch (_action[custom_key]) {
624         case CUSTOM_ACTION_PAN_NORTH:
625                 gtk_map_pan(_map, 0, -1);
626         break;
627         case CUSTOM_ACTION_PAN_WEST:
628                 gtk_map_pan(_map, -1, 0);
629         break;
630         case CUSTOM_ACTION_PAN_SOUTH:
631                 gtk_map_pan(_map, 0, 1);
632         break;
633         case CUSTOM_ACTION_PAN_EAST:
634                 gtk_map_pan(_map, 1, 0);
635         break;
636         case CUSTOM_ACTION_TOGGLE_AUTOCENTER:
637                 g_object_get(_map, "center-mode", &cm);
638                 switch (cm) {
639                         case CENTER_LATLON:
640                         case CENTER_WAS_LEAD:
641                                 set_action_activate("autocenter_lead", TRUE);
642                         break;
643                         case CENTER_LEAD:
644                         case CENTER_WAS_LATLON:
645                                 set_action_activate("autocenter_latlon", TRUE);
646                         break;
647                         default:
648                                 set_action_activate("autocenter_latlon", TRUE);
649                         break;
650                 }
651         break;
652         case CUSTOM_ACTION_ZOOM_IN:
653                 gtk_map_zoom_in(_map);
654         break;
655         case CUSTOM_ACTION_ZOOM_OUT:
656                 gtk_map_zoom_out(_map);
657         break;
658         case CUSTOM_ACTION_TOGGLE_FULLSCREEN:
659                 set_action_activate("view_fullscreen", !_fullscreen);
660         break;
661         case CUSTOM_ACTION_TOGGLE_TRACKS:
662                 switch (_show_tracks) {
663                 case 0:
664                         /* Nothing shown, nothing saved; just set both. */
665                         _show_tracks = TRACKS_MASK | ROUTES_MASK;
666                         break;
667                 case TRACKS_MASK << 16:
668                 case ROUTES_MASK << 16:
669                 case (ROUTES_MASK | TRACKS_MASK) << 16:
670                         /* Something was saved and nothing changed since.
671                          * Restore saved. */
672                         _show_tracks = _show_tracks >> 16;
673                         break;
674                 default:
675                         /* There is no history, or they changed something
676                          * since the last historical change. Save and
677                          * clear. */
678                         _show_tracks = _show_tracks << 16;
679                 }
680                 set_action_activate("view_route", _show_tracks & ROUTES_MASK);
681                 set_action_activate("view_track", _show_tracks & TRACKS_MASK);
682         break;
683         case CUSTOM_ACTION_TOGGLE_SCALE:
684                 set_action_activate("view_scale", _show_scale);
685         break;
686         case CUSTOM_ACTION_TOGGLE_POI:
687                 set_action_activate("view_poi", _show_poi);
688         break;
689         case CUSTOM_ACTION_CHANGE_REPO: {
690                         GList *curr = g_list_find(_repo_list, _curr_repo);
691                         if (!curr)
692                                 break;
693
694                         /* Loop until we reach a next-able repo, or until we get
695                          * back to the current repo. */
696                         while ((curr = (curr->next ? curr->next : _repo_list)) && !((RepoData *) curr->data)->nextable && curr->data != _curr_repo) {
697                         }
698
699                         if (curr->data != _curr_repo) {
700                                 repo_set_curr(curr->data);
701                                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(_curr_repo->menu_item), TRUE);
702                         } else {
703                                 popup_error(_window, _("There are no other next-able repositories."));
704                         }
705                         break;
706                 }
707         break;
708         case CUSTOM_ACTION_ROUTE_DISTNEXT:
709                 path_show_distance_to_next(_route);
710         break;
711         case CUSTOM_ACTION_ROUTE_DISTLAST:
712                 path_show_distance_to_last(_route);
713         break;
714         case CUSTOM_ACTION_TRACK_BREAK:
715                 path_add_break(_track);
716         break;
717         case CUSTOM_ACTION_TRACK_DISTLAST:
718                 path_show_distance_from_last(_track);
719         break;
720         case CUSTOM_ACTION_TRACK_DISTFIRST:
721                 path_show_distance_from_first(_track);
722         break;
723         case CUSTOM_ACTION_TOGGLE_GPS:
724                 set_action_activate("gps_enable", !_enable_gps);
725         break;
726         case CUSTOM_ACTION_TOGGLE_GPSINFO:
727                 set_action_activate("gps_info", !_gps_info);
728         break;
729         case CUSTOM_ACTION_TOGGLE_SPEEDLIMIT:
730                 _speed_on ^= 1;
731         break;
732         default:
733                 return FALSE;
734 }
735 return TRUE;
736 }
737
738 gboolean 
739 window_cb_key_release(GtkWidget * widget, GdkEventKey * event)
740 {
741 switch (event->keyval) {
742         case HILDON_HARDKEY_INCREASE:
743                 gtk_map_zoom_in(_map);
744         break;
745         case HILDON_HARDKEY_DECREASE:
746                 gtk_map_zoom_out(_map);
747         break;
748         default:
749         break;
750 }
751 return FALSE;
752 }
753
754 void 
755 cmenu_show_latlon(gdouble lat, gdouble lon)
756 {
757 gchar buffer[80], tmp1[16], tmp2[16];
758
759 lat_format(_degformat, lat, tmp1);
760 lon_format(_degformat, lon, tmp2);
761
762 g_snprintf(buffer, sizeof(buffer), "%s: %s\n%s: %s", _("Latitude"), tmp1, _("Longitude"), tmp2);
763 /* XXX: Use a dialog under plain Gtk */
764 MACRO_BANNER_SHOW_INFO(_window, buffer);
765 }
766
767 void 
768 cmenu_clip_latlon(gdouble lat, gdouble lon)
769 {
770 gchar buffer[80];
771
772 g_snprintf(buffer, sizeof(buffer), "%.06f,%.06f", lat, lon);
773
774 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
775 }
776
777 void 
778 cmenu_route_to(gdouble lat, gdouble lon)
779 {
780 gchar buffer[80];
781 gchar strlat[32];
782 gchar strlon[32];
783
784 g_ascii_formatd(strlat, 32, "%.06f", lat);
785 g_ascii_formatd(strlon, 32, "%.06f", lon);
786 g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
787
788 route_download(_route, buffer);
789 }
790
791 void 
792 cmenu_distance_to(gdouble lat, gdouble lon)
793 {
794 gchar buffer[80];
795
796 g_snprintf(buffer, sizeof(buffer), "%s: %.02lf %s", _("Distance"),
797          calculate_distance(_gps->data.lat, _gps->data.lon, lat, lon) * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
798 MACRO_BANNER_SHOW_INFO(_window, buffer);
799 }
800
801 void
802 cmenu_route_add_way(gdouble lat, gdouble lon)
803 {
804 gchar tmp1[16], tmp2[16], *p_latlon;
805 GtkWidget *dialog;
806 GtkWidget *table;
807 GtkWidget *label;
808 GtkWidget *txt_scroll;
809 GtkWidget *txt_desc;
810
811 dialog = gtk_dialog_new_with_buttons(_("Add Waypoint"),
812                              GTK_WINDOW(_window),
813                              GTK_DIALOG_MODAL, GTK_STOCK_OK,
814                              GTK_RESPONSE_ACCEPT,
815                              GTK_STOCK_CANCEL,
816                              GTK_RESPONSE_REJECT, NULL);
817
818 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0);
819
820 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
821 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
822
823 lat_format(_degformat, lat, tmp1);
824 lon_format(_degformat, lon, tmp2);
825 p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2);
826 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(p_latlon), 1, 2, 0, 1, GTK_FILL, 0, 2, 4);
827 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
828 g_free(p_latlon);
829
830 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Description")), 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
831 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
832
833 txt_scroll = gtk_scrolled_window_new(NULL, NULL);
834 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), GTK_SHADOW_IN);
835 gtk_table_attach(GTK_TABLE(table), txt_scroll, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
836
837 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
838
839 txt_desc = gtk_text_view_new();
840 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
841
842 gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
843 gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
844
845 gtk_widget_show_all(dialog);
846
847 while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
848         GtkTextBuffer *tbuf;
849         GtkTextIter ti1, ti2;
850         gchar *desc;
851
852         tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
853         gtk_text_buffer_get_iter_at_offset(tbuf, &ti1, 0);
854         gtk_text_buffer_get_end_iter(tbuf, &ti2);
855         desc = gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE);
856
857         path_add_waypoint(_route, lat, lon, desc);
858         break;
859 }
860 gtk_widget_destroy(dialog);
861 }
862
863 gboolean 
864 cmenu_cb_loc_show_latlon(GtkAction *action)
865 {
866 gdouble lat, lon;
867
868 gtk_map_get_menu_latlon(_map, &lat, &lon);
869 cmenu_show_latlon(lat, lon);
870 return TRUE;
871 }
872
873 gboolean 
874 cmenu_cb_loc_clip_latlon(GtkAction *action)
875 {
876 gdouble lat, lon;
877
878 gtk_map_get_menu_latlon(_map, &lat, &lon);
879 cmenu_clip_latlon(lat, lon);
880 return TRUE;
881 }
882
883 gboolean 
884 cmenu_cb_loc_route_to(GtkAction *action)
885 {
886 gdouble lat, lon;
887
888 gtk_map_get_menu_latlon(_map, &lat, &lon);
889 cmenu_route_to(lat, lon);
890 return TRUE;
891 }
892
893 gboolean 
894 cmenu_cb_loc_distance_to(GtkAction *action)
895 {
896 gdouble lat, lon;
897
898 gtk_map_get_menu_latlon(_map, &lat, &lon);
899 cmenu_distance_to(lat, lon);
900 return TRUE;
901 }
902
903 gboolean 
904 cmenu_cb_loc_add_route(GtkAction *action)
905 {
906 gdouble lat, lon;
907
908 gtk_map_get_menu_latlon(_map, &lat, &lon);
909 path_add_latlon(_route, lat, lon, time(NULL), 0, 0);
910 return TRUE;
911 }
912
913 gboolean 
914 cmenu_cb_loc_add_way(GtkAction *action)
915 {
916 gdouble lat, lon;
917
918 gtk_map_get_menu_latlon(_map, &lat, &lon);
919 cmenu_route_add_way(lat, lon);
920 return TRUE;
921 }
922
923 gboolean 
924 cmenu_cb_loc_add_poi(GtkAction *action)
925 {
926 poi_info *poi;
927
928 poi=poi_new();
929 gtk_map_get_menu_latlon(_map, &poi->lat, &poi->lon);
930 poi_edit_dialog(ACTION_ADD_POI, poi);
931
932 return TRUE;
933 }
934
935 gboolean
936 cb_poi_search(GtkAction *action)
937 {
938 poi_info poi;
939 gdouble lat, lon;
940 GtkMapCenterMode cm;
941
942 g_object_get(_map, "center-mode", &cm);
943 if (cm!=CENTER_MANUAL) {
944         lat=_gps->data.lat;
945         lon=_gps->data.lon;
946 } else {
947         gtk_map_get_center_latlon(_map, &lat, &lon);
948 }
949
950 mapper_search_dialog(SEARCH_TYPE_POI, lat, lon);
951 return TRUE;
952 }
953
954 gboolean 
955 cb_poi_add(GtkAction *action)
956 {
957 gdouble lat,lon;
958 const gchar *name = gtk_action_get_name(action);
959 poi_info *p;
960
961 if (gtk_map_get_center_mode(_map)!=CENTER_MANUAL) {
962         lat=_gps->data.lat;
963         lon=_gps->data.lon;
964 } else {
965         gtk_map_get_center_latlon(_map, &lat, &lon);
966 }
967
968 if (strcmp(name, "poi_add")==0) {
969         p=poi_new();
970         p->lat=lat;
971         p->lon=lon;
972         poi_edit_dialog(ACTION_ADD_POI, p);
973         map_poi_cache_clear();
974 } else if (strcmp(name, "poi_quick_add")==0) {
975         poi_quick_dialog(lat, lon);
976         map_poi_cache_clear();
977 } else
978         g_assert_not_reached();
979
980 return TRUE;
981 }
982
983 gboolean
984 menu_cb_search_address(GtkAction *action)
985 {
986 gdouble lat, lon;
987
988 if (gtk_map_get_center_mode(_map)!=CENTER_MANUAL) {
989         lat=_gps->data.lat;
990         lon=_gps->data.lon;
991 } else {
992         gtk_map_get_center_latlon(_map, &lat, &lon);
993 }
994 mapper_search_dialog(SEARCH_TYPE_WAY, lat, lon);
995 return TRUE;
996 }
997
998 gboolean 
999 cmenu_cb_loc_set_home(GtkAction *action)
1000 {
1001 gtk_map_get_menu_latlon(_map, &_home->lat, &_home->lon);
1002 _home->valid=TRUE;
1003
1004 if (!config_save_position(_home, GCONF_KEY_POSITION_HOME))
1005         popup_error(_window, _("Failed to save home position."));
1006
1007 gtk_map_refresh(_map);
1008 return TRUE;
1009 }
1010
1011 gboolean 
1012 cmenu_cb_loc_set_destination(GtkAction *action)
1013 {
1014 gtk_map_get_menu_latlon(_map, &_dest->lat, &_dest->lon);
1015 _dest->valid=TRUE;
1016
1017 if (!config_save_position(&_dest, GCONF_KEY_POSITION_DEST))
1018         popup_error(_window, _("Failed to save destination."));
1019
1020 gtk_map_refresh(_map);
1021 return TRUE;
1022 }
1023
1024 gboolean 
1025 cmenu_cb_loc_set_gps(GtkAction *action)
1026 {
1027 gtk_map_get_menu_latlon(_map, &_gps->data.lat, &_gps->data.lon);
1028 path_add_latlon(_track, _gps->data.lat, _gps->data.lon, time(NULL), 0, NAN);
1029
1030 return TRUE;
1031 }
1032
1033 gboolean 
1034 cmenu_cb_way_show_latlon(GtkAction *action)
1035 {
1036 WayPoint *way;
1037 gdouble lat, lon;
1038
1039 gtk_map_get_menu_latlon(_map, &lat, &lon);
1040
1041 if ((way = path_find_nearest_waypoint(_route, lat, lon)))
1042                 cmenu_show_latlon(lat, lon);
1043
1044 return TRUE;
1045 }
1046
1047 gboolean 
1048 cmenu_cb_way_show_desc(GtkAction *action)
1049 {
1050 WayPoint *way;
1051 gdouble lat, lon;
1052
1053 gtk_map_get_menu_latlon(_map, &lat, &lon);
1054
1055 if ((way = path_find_nearest_waypoint(_route, lat, lon)))
1056         MACRO_BANNER_SHOW_INFO(_window, way->desc);
1057
1058 return TRUE;
1059 }
1060
1061 gboolean 
1062 cmenu_cb_way_clip_latlon(GtkAction *action)
1063 {
1064 WayPoint *way;
1065 gdouble lat, lon;
1066
1067 gtk_map_get_menu_latlon(_map, &lat, &lon);
1068 if ((way = path_find_nearest_waypoint(_route, lat, lon)))
1069                 cmenu_clip_latlon(way->point->unitx, way->point->unity);
1070
1071 return TRUE;
1072 }
1073
1074 gboolean 
1075 cmenu_cb_way_clip_desc(GtkAction *action)
1076 {
1077 WayPoint *way;
1078 gdouble lat, lon;
1079
1080 gtk_map_get_menu_latlon(_map, &lat, &lon);
1081 if ((way = path_find_nearest_waypoint(_route, lat, lon)))
1082         gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), way->desc, -1);
1083
1084 return TRUE;
1085 }
1086
1087 gboolean 
1088 cmenu_cb_way_route_to(GtkAction *action)
1089 {
1090 WayPoint *way;
1091 gdouble lat, lon;
1092
1093 gtk_map_get_menu_latlon(_map, &lat, &lon);
1094
1095 if ((way = path_find_nearest_waypoint(_route, lat, lon)))
1096         cmenu_route_to(way->point->unitx, way->point->unity);
1097
1098 return TRUE;
1099 }
1100
1101 gboolean 
1102 cmenu_cb_way_distance_to(GtkAction *action)
1103 {
1104 WayPoint *way;
1105 gdouble lat, lon;
1106
1107 gtk_map_get_menu_latlon(_map, &lat, &lon);
1108
1109 if ((way = route_find_nearest_waypoint(_route, lat, lon)))
1110         route_show_distance_to(_route, way->point);
1111
1112 return TRUE;
1113 }
1114
1115 gboolean 
1116 cmenu_cb_way_delete(GtkAction *action)
1117 {
1118 WayPoint *way;
1119 gdouble lat, lon;
1120
1121 gtk_map_get_menu_latlon(_map, &lat, &lon);
1122
1123 if ((way = path_find_nearest_waypoint(_route, lat, lon))) {
1124         gchar buffer[BUFFER_SIZE];
1125         GtkWidget *confirm;
1126
1127         g_snprintf(buffer, sizeof(buffer), "%s:\n%s\n", _("Confirm delete of waypoint"), way->desc);
1128         confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
1129
1130         if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) {
1131                 Point *pdel_min, *pdel_max, *pdel_start, *pdel_end;
1132                 guint num_del;
1133
1134                 /* Delete surrounding route data, too. */
1135                 if (way == _route->whead)
1136                         pdel_min = _route->head;
1137                 else
1138                         pdel_min = way[-1].point;
1139
1140                 if (way == _route->wtail)
1141                         pdel_max = _route->tail;
1142                 else
1143                         pdel_max = way[1].point;
1144
1145                 /* Find largest continuous segment around the waypoint, EXCLUDING pdel_min and pdel_max. */
1146                 for (pdel_start = way->point - 1; pdel_start->unity && pdel_start > pdel_min; pdel_start--) {
1147                 }
1148                 for (pdel_end = way->point + 1; pdel_end->unity && pdel_end < pdel_max; pdel_end++) {
1149                 }
1150
1151                 /* If pdel_end is set to _route->tail, and if _route->tail is a non-zero point, then delete _route->tail. */
1152                 if (pdel_end == _route->tail && pdel_end->unity)
1153                         pdel_end++;     /* delete _route->tail too */
1154                 /* else, if *both* endpoints are zero points, delete one. */
1155                 else if (!pdel_start->unity && !pdel_end->unity)
1156                         pdel_start--;
1157
1158                 /* Delete BETWEEN pdel_start and pdel_end, exclusive. */
1159                 num_del = pdel_end - pdel_start - 1;
1160
1161                 memmove(pdel_start + 1, pdel_end,(_route->tail - pdel_end + 1) * sizeof(Point));
1162                 _route->tail -= num_del;
1163
1164                 /* Remove waypoint and move/adjust subsequent waypoints. */
1165                 g_free(way->desc);
1166                 while (way++ != _route->wtail) {
1167                         way[-1] = *way;
1168                         way[-1].point -= num_del;
1169                 }
1170                 _route->wtail--;
1171 #if 0
1172                 path_find_nearest_point(_route);
1173 #endif
1174         }
1175         gtk_widget_destroy(confirm);
1176 }
1177
1178 return TRUE;
1179 }
1180
1181 gboolean
1182 menu_cb_category(GtkAction *action)
1183 {
1184 if (poi_category_list())
1185         gtk_map_refresh(_map);
1186
1187 return TRUE;
1188 }
1189
1190 gboolean 
1191 cmenu_cb_way_add_poi(GtkAction *action)
1192 {
1193 WayPoint *way;
1194 gdouble lat, lon;
1195
1196 gtk_map_get_menu_latlon(_map, &lat, &lon);
1197
1198 if ((way = path_find_nearest_waypoint(_route, lat, lon))) {
1199         poi_info *p;
1200
1201         p=poi_new();
1202         path_get_waypoint_latlon(way, &p->lat, &p->lon);
1203         poi_edit_dialog(ACTION_ADD_POI, p);
1204 }
1205 return TRUE;
1206 }
1207
1208 gboolean 
1209 cmenu_cb_poi_route_to(GtkAction *action)
1210 {
1211 poi_info poi;
1212 gdouble lat, lon;
1213
1214 gtk_map_get_menu_latlon(_map, &lat, &lon);
1215 if (poi_select(lat, lon, 4, &poi))
1216         cmenu_route_to(poi.lat, poi.lon);
1217
1218 return TRUE;
1219 }
1220
1221 gboolean 
1222 cmenu_cb_poi_distance_to(GtkAction *action)
1223 {
1224 poi_info poi;
1225 gdouble lat, lon;
1226
1227 gtk_map_get_menu_latlon(_map, &lat, &lon);
1228
1229 if (poi_select(lat, lon, 4, &poi))
1230         cmenu_distance_to(poi.lat, poi.lon);
1231
1232 return TRUE;
1233 }
1234
1235 gboolean 
1236 cmenu_cb_poi_add_route(GtkAction *action)
1237 {
1238 poi_info poi;
1239 gdouble lat, lon;
1240
1241 gtk_map_get_menu_latlon(_map, &lat, &lon);
1242 if (poi_select(lat, lon, 4, &poi))
1243         path_add_latlon(_route, lat, lon, time(NULL), 0, 0);
1244
1245 return TRUE;
1246 }
1247
1248 gboolean 
1249 cmenu_cb_poi_add_way(GtkAction *action)
1250 {
1251 poi_info poi;
1252 gdouble lat, lon;
1253
1254 gtk_map_get_menu_latlon(_map, &lat, &lon);
1255
1256 if (poi_select(lat, lon, 4, &poi))
1257         cmenu_route_add_way(lat, lon);
1258
1259 return TRUE;
1260 }
1261
1262 gboolean
1263 cmenu_cb_poi_show_poi(GtkAction *action)
1264 {
1265 /* XXX: Write this */
1266 return TRUE;
1267 }
1268
1269 gboolean 
1270 cmenu_cb_poi_edit_poi(GtkAction *action)
1271 {
1272 poi_info *p;
1273 gdouble lat, lon;
1274
1275 gtk_map_get_menu_latlon(_map, &lat, &lon);
1276 p=poi_find_nearest(lat, lon);
1277 if (!p) {
1278         popup_error(_window, _("No POI found at location."));
1279         return TRUE;
1280 }
1281 poi_edit_dialog(ACTION_EDIT_POI, p);
1282 return TRUE;
1283 }
1284
1285 /***/
1286
1287 gboolean 
1288 headphone_button_cb(gpointer data)
1289 {
1290 gint hb_action=0;
1291 switch (hb_action) {
1292 case 1:
1293 #if 0
1294         /* XXX: Add code to add generic POI */
1295         hildon_banner_show_information(_window, NULL, _("POI Added"));
1296 #endif
1297 break;
1298 case 0:
1299 default:
1300         path_insert_mark_text(_track, g_strdup("Mark"));
1301         hildon_banner_show_information(_window, NULL, _("Mark added"));
1302 break;
1303 }
1304 return FALSE;
1305