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