Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 158 - (show annotations)
Fri Apr 10 11:13:26 2009 UTC (15 years, 1 month ago) by harbaum
File MIME type: text/plain
File size: 33923 byte(s)
Initial API 0.6 support
1 /*
2 * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3 *
4 * This file is part of OSM2Go.
5 *
6 * OSM2Go is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * OSM2Go is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with OSM2Go. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #include <curl/curl.h>
24 #include <gdk/gdkkeysyms.h>
25
26 #include "appdata.h"
27 #include "banner.h"
28
29 /* disable/enable main screen control dependant on presence of open project */
30 static void main_ui_enable(appdata_t *appdata) {
31 gboolean project_valid = (appdata->project != NULL);
32 gboolean osm_valid = (appdata->osm != NULL);
33
34 /* cancel any action in progress */
35 if(GTK_WIDGET_FLAGS(appdata->iconbar->cancel) & GTK_SENSITIVE)
36 map_action_cancel(appdata);
37
38 /* ---- set project name as window title ----- */
39 #ifndef USE_HILDON
40 char *str = NULL;
41 if(project_valid)
42 str = g_strdup_printf("OSM2Go - %s", appdata->project->name);
43 else
44 str = g_strdup_printf("OSM2Go");
45
46 gtk_window_set_title(GTK_WINDOW(appdata->window), str);
47 g_free(str);
48 #else
49 if(project_valid)
50 gtk_window_set_title(GTK_WINDOW(appdata->window), appdata->project->name);
51 else
52 gtk_window_set_title(GTK_WINDOW(appdata->window), "");
53 #endif
54
55 if(appdata->iconbar && appdata->iconbar->toolbar)
56 gtk_widget_set_sensitive(appdata->iconbar->toolbar, osm_valid);
57
58 /* disable all menu entries related to map */
59 gtk_widget_set_sensitive(appdata->menu_osm, project_valid);
60 gtk_widget_set_sensitive(appdata->menu_item_osm_upload, osm_valid);
61 if(appdata->menu_item_osm_undo)
62 gtk_widget_set_sensitive(appdata->menu_item_osm_undo, osm_valid);
63 gtk_widget_set_sensitive(appdata->menu_item_osm_save_changes, osm_valid);
64 gtk_widget_set_sensitive(appdata->menu_item_osm_undo_changes, osm_valid);
65 gtk_widget_set_sensitive(appdata->menu_item_osm_relations, osm_valid);
66 gtk_widget_set_sensitive(appdata->track.menu_track, osm_valid);
67 gtk_widget_set_sensitive(appdata->menu_view, osm_valid);
68 gtk_widget_set_sensitive(appdata->menu_wms, osm_valid);
69 gtk_widget_set_sensitive(appdata->menu_map, osm_valid);
70 gtk_widget_set_sensitive(appdata->menu_item_project_close, project_valid);
71
72 if(!project_valid)
73 statusbar_set(appdata, _("Please load or create a project"), FALSE);
74 }
75
76 /******************** begin of menu *********************/
77
78 static void
79 cb_menu_project_open(GtkMenuItem *item, gpointer data) {
80 appdata_t *appdata = (appdata_t*)data;
81 project_load(appdata, NULL);
82 main_ui_enable(appdata);
83 }
84
85 static void
86 cb_menu_project_close(GtkMenuItem *item, gpointer data) {
87 appdata_t *appdata = (appdata_t*)data;
88 project_close(appdata);
89 main_ui_enable(appdata);
90 }
91
92 static void
93 cb_menu_about(GtkMenuItem *item, gpointer data) {
94 appdata_t *appdata = (appdata_t*)data;
95
96 const gchar *authors[] = {
97 "Till Harbaum <till@harbaum.org>",
98 "Andrew Chadwick <andrewc-osm2go@piffle.org>",
99 NULL };
100
101 const gchar *artists[] = {
102 "Andrew Zhilin <drew.zhilin@gmail.com>",
103 NULL };
104
105 gtk_show_about_dialog(GTK_WINDOW(appdata->window),
106 "name", "OSM2Go",
107 "version", VERSION,
108 "copyright", _("Copyright 2008-2009"),
109 "authors", authors,
110 "artists", artists,
111 "website", _("http://www.harbaum.org/till/maemo"),
112 "comments", _("Mobile OSM Editor"),
113 NULL);
114 }
115
116 void on_window_destroy (GtkWidget *widget, gpointer data);
117
118 static void
119 cb_menu_quit(GtkMenuItem *item, gpointer data) {
120 appdata_t *appdata = (appdata_t*)data;
121 gtk_widget_destroy(GTK_WIDGET(appdata->window));
122 }
123
124 static void
125 cb_menu_upload(GtkMenuItem *item, gpointer data) {
126 appdata_t *appdata = (appdata_t*)data;
127 if(!appdata->osm || !appdata->project) return;
128
129 osm_upload(appdata, appdata->osm, appdata->project);
130 }
131
132 static void
133 cb_menu_download(GtkMenuItem *item, gpointer data) {
134 appdata_t *appdata = (appdata_t*)data;
135 if(!appdata->project) return;
136
137 /* if we have valid osm data loaded: save state first */
138 if(appdata->osm) {
139 /* redraw the entire map by destroying all map items and redrawing them */
140 diff_save(appdata->project, appdata->osm);
141 map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
142 osm_free(&appdata->icon, appdata->osm);
143
144 appdata->osm = NULL;
145 }
146
147 // download
148 if(osm_download(GTK_WIDGET(appdata->window), appdata->project)) {
149 banner_busy_start(appdata, 1, "Redrawing...");
150 appdata->osm = osm_parse(appdata->project->osm);
151 diff_restore(appdata, appdata->project, appdata->osm);
152 map_paint(appdata);
153 banner_busy_stop(appdata); //"Redrawing..."
154 }
155
156 main_ui_enable(appdata);
157 }
158
159 static void
160 cb_menu_wms_import(GtkMenuItem *item, gpointer data) {
161 appdata_t *appdata = (appdata_t*)data;
162 wms_import(appdata);
163 }
164
165 static void
166 cb_menu_wms_clear(GtkMenuItem *item, gpointer data) {
167 appdata_t *appdata = (appdata_t*)data;
168 wms_remove(appdata);
169 }
170
171 static void
172 cb_menu_wms_adjust(GtkMenuItem *item, gpointer data) {
173 appdata_t *appdata = (appdata_t*)data;
174 map_action_set(appdata, MAP_ACTION_BG_ADJUST);
175 }
176
177 /* ----------- hide objects for performance reasons ----------- */
178
179 static void
180 cb_menu_map_hide_sel(GtkMenuItem *item, gpointer data) {
181 appdata_t *appdata = (appdata_t*)data;
182 map_hide_selected(appdata);
183 }
184
185 static void
186 cb_menu_map_show_all(GtkMenuItem *item, gpointer data) {
187 appdata_t *appdata = (appdata_t*)data;
188 map_show_all(appdata);
189 }
190
191 /* ---------------------------------------------------------- */
192
193 #if 1 // mainly for testing
194 static void
195 cb_menu_redraw(GtkMenuItem *item, gpointer data) {
196 appdata_t *appdata = (appdata_t*)data;
197
198 /* redraw the entire map by destroying all map items and redrawing them */
199 banner_busy_start(appdata, 1, "Redrawing...");
200 track_save(appdata->project, appdata->track.track);
201 diff_save(appdata->project, appdata->osm);
202 map_clear(appdata, MAP_LAYER_ALL);
203 osm_free(&appdata->icon, appdata->osm);
204
205 appdata->osm = osm_parse(appdata->project->osm);
206 diff_restore(appdata, appdata->project, appdata->osm);
207 map_paint(appdata);
208
209 appdata->track.track = track_restore(appdata, appdata->project);
210 if(appdata->track.track)
211 map_track_draw(appdata->map, appdata->track.track);
212
213 wms_load(appdata);
214 banner_busy_stop(appdata); //"Redrawing..."
215 }
216 #endif
217
218 static void
219 cb_menu_style(GtkMenuItem *item, gpointer data) {
220 appdata_t *appdata = (appdata_t*)data;
221
222 style_select(GTK_WIDGET(appdata->window), appdata);
223 }
224
225 static void
226 cb_menu_map_no_icons(GtkCheckMenuItem *item, gpointer data) {
227 appdata_t *appdata = (appdata_t*)data;
228
229 banner_busy_start(appdata, 1, "Redrawing...");
230 map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
231 appdata->settings->no_icons = gtk_check_menu_item_get_active(item);
232 map_paint(appdata);
233 banner_busy_stop(appdata); //"Redrawing..."
234 }
235
236 static void
237 cb_menu_map_no_antialias(GtkCheckMenuItem *item, gpointer data) {
238 appdata_t *appdata = (appdata_t*)data;
239
240 banner_busy_start(appdata, 1, "Redrawing...");
241 map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
242 appdata->settings->no_antialias = gtk_check_menu_item_get_active(item);
243 map_paint(appdata);
244 banner_busy_stop(appdata); //"Redrawing..."
245 }
246
247 static void
248 cb_menu_undo(GtkMenuItem *item, gpointer data) {
249 appdata_t *appdata = (appdata_t*)data;
250
251 undo(appdata);
252
253 // the banner will be displayed from within undo with more details
254 }
255
256 static void
257 cb_menu_save_changes(GtkMenuItem *item, gpointer data) {
258 appdata_t *appdata = (appdata_t*)data;
259
260 diff_save(appdata->project, appdata->osm);
261 banner_show_info(appdata, _("Saved local changes"));
262 }
263
264 static void
265 cb_menu_undo_changes(GtkMenuItem *item, gpointer data) {
266 appdata_t *appdata = (appdata_t*)data;
267
268 if(!yes_no_f(GTK_WIDGET(appdata->window), NULL, 0, 0,
269 _("Discard local changes?"),
270 _("Throw away all the changes you've not "
271 "uploaded yet? This can't be undone.")))
272 return;
273
274 banner_busy_start(appdata, 1, _("Redrawing..."));
275 map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
276 osm_free(&appdata->icon, appdata->osm);
277 diff_remove(appdata->project);
278 appdata->osm = osm_parse(appdata->project->osm);
279 map_paint(appdata);
280 banner_busy_stop(appdata); //"Redrawing..."
281
282 banner_show_info(appdata, _("Discarded local changes"));
283 }
284
285 static void
286 cb_menu_osm_relations(GtkMenuItem *item, gpointer data) {
287 relation_list((appdata_t*)data);
288 }
289
290 static void
291 cb_menu_fullscreen(GtkCheckMenuItem *item, gpointer data) {
292 appdata_t *appdata = (appdata_t *)data;
293
294 if(gtk_check_menu_item_get_active(item))
295 gtk_window_fullscreen(GTK_WINDOW(appdata->window));
296 else
297 gtk_window_unfullscreen(GTK_WINDOW(appdata->window));
298 }
299
300 static void
301 cb_menu_zoomin(GtkMenuItem *item, appdata_t *appdata) {
302 if(!appdata || !appdata->map) return;
303
304 map_set_zoom(appdata->map, appdata->map->state->zoom*ZOOM_FACTOR_MENU, TRUE);
305 printf("zoom is now %f\n", appdata->map->state->zoom);
306 }
307
308 static void
309 cb_menu_zoomout(GtkMenuItem *item, appdata_t *appdata) {
310 if(!appdata || !appdata->map) return;
311
312 map_set_zoom(appdata->map, appdata->map->state->zoom/ZOOM_FACTOR_MENU, TRUE);
313 printf("zoom is now %f\n", appdata->map->state->zoom);
314 }
315
316 static void
317 cb_menu_track_import(GtkMenuItem *item, appdata_t *appdata) {
318 g_assert(appdata->settings);
319
320 /* open a file selector */
321 GtkWidget *dialog;
322
323 #ifdef USE_HILDON
324 dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(appdata->window),
325 GTK_FILE_CHOOSER_ACTION_OPEN);
326 #else
327 dialog = gtk_file_chooser_dialog_new (_("Import track file"),
328 GTK_WINDOW(appdata->window),
329 GTK_FILE_CHOOSER_ACTION_OPEN,
330 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
331 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
332 NULL);
333 #endif
334
335 if(appdata->settings->track_path) {
336 if(!g_file_test(appdata->settings->track_path, G_FILE_TEST_EXISTS)) {
337 char *last_sep = strrchr(appdata->settings->track_path, '/');
338 if(last_sep) {
339 *last_sep = 0; // seperate path from file
340
341 /* the user just created a new document */
342 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
343 appdata->settings->track_path);
344 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
345 last_sep+1);
346
347 /* restore full filename */
348 *last_sep = '/';
349 }
350 } else
351 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
352 appdata->settings->track_path);
353 }
354
355 gtk_widget_show_all (GTK_WIDGET(dialog));
356 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {
357 char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
358
359 /* load a track */
360 appdata->track.track = track_import(appdata, filename);
361 if(appdata->track.track) {
362 if(appdata->settings->track_path) g_free(appdata->settings->track_path);
363 appdata->settings->track_path = g_strdup(filename);
364 }
365 g_free (filename);
366 }
367
368 gtk_widget_destroy (dialog);
369 }
370
371 static void
372 cb_menu_track_enable_gps(GtkMenuItem *item, gpointer data) {
373 appdata_t *appdata = (appdata_t*)data;
374
375 if(gtk_check_menu_item_get_active(
376 GTK_CHECK_MENU_ITEM(appdata->track.menu_item_enable_gps))) {
377 track_enable_gps(appdata, TRUE);
378 } else
379 track_enable_gps(appdata, FALSE);
380 }
381
382
383 static void
384 cb_menu_track_follow_gps(GtkMenuItem *item, gpointer data) {
385 appdata_t *appdata = (appdata_t*)data;
386
387 if(gtk_check_menu_item_get_active(
388 GTK_CHECK_MENU_ITEM(appdata->track.menu_item_follow_gps))) {
389 appdata->settings->follow_gps = TRUE;
390 } else
391 appdata->settings->follow_gps = FALSE;
392 }
393
394
395 static void
396 cb_menu_track_export(GtkMenuItem *item, appdata_t *appdata) {
397 g_assert(appdata->settings);
398
399 /* open a file selector */
400 GtkWidget *dialog;
401
402 #ifdef USE_HILDON
403 dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(appdata->window),
404 GTK_FILE_CHOOSER_ACTION_SAVE);
405 #else
406 dialog = gtk_file_chooser_dialog_new(_("Export track file"),
407 GTK_WINDOW(appdata->window),
408 GTK_FILE_CHOOSER_ACTION_SAVE,
409 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
410 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
411 NULL);
412 #endif
413
414 printf("set filename <%s>\n", appdata->settings->track_path);
415
416 if(appdata->settings->track_path) {
417 if(!g_file_test(appdata->settings->track_path, G_FILE_TEST_EXISTS)) {
418 char *last_sep = strrchr(appdata->settings->track_path, '/');
419 if(last_sep) {
420 *last_sep = 0; // seperate path from file
421
422 /* the user just created a new document */
423 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
424 appdata->settings->track_path);
425 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
426 last_sep+1);
427
428 /* restore full filename */
429 *last_sep = '/';
430 }
431 } else
432 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
433 appdata->settings->track_path);
434 }
435
436 if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_FM_OK) {
437 gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
438 if(filename) {
439 printf("export to %s\n", filename);
440
441 if(!g_file_test(filename, G_FILE_TEST_EXISTS) ||
442 yes_no_f(dialog, appdata, MISC_AGAIN_ID_EXPORT_OVERWRITE,
443 MISC_AGAIN_FLAG_DONT_SAVE_NO,
444 "Overwrite existing file",
445 "The file already exists. "
446 "Do you really want to replace it?")) {
447 if(appdata->settings->track_path)
448 g_free(appdata->settings->track_path);
449 appdata->settings->track_path = g_strdup(filename);
450
451 track_export(appdata, filename);
452 }
453 }
454 }
455
456 gtk_widget_destroy (dialog);
457 }
458
459
460 static void
461 cb_menu_track_clear(GtkMenuItem *item, gpointer data) {
462 appdata_t *appdata = (appdata_t*)data;
463 track_clear(appdata, appdata->track.track);
464 appdata->track.track = NULL;
465 }
466
467
468
469
470 /*
471 * Platform-specific UI tweaks.
472 */
473
474
475 #ifndef USE_HILDON
476 #ifdef PORTRAIT
477
478 // Portrait mode, for openmoko-like systems
479 #define uispecific_main_menu_new gtk_menu_new
480
481 #else
482
483 // Regular desktop builds
484 #define uispecific_main_menu_new gtk_menu_bar_new
485 #define UISPECIFIC_MAIN_MENU_IS_MENU_BAR
486 #define UISPECIFIC_MENU_HAS_ICONS
487 #define UISPECIFIC_MENU_HAS_ACCELS
488
489 #endif //PORTRAIT
490 #else//USE_HILDON
491
492 // Maemo/Hildon builds
493 #define uispecific_main_menu_new gtk_menu_new
494
495 #endif
496
497
498
499 // Half-arsed slapdash common menu item constructor. Let's use GtkBuilder
500 // instead so we have some flexibility.
501
502 static GtkWidget *
503 menu_append_new_item(appdata_t *appdata,
504 GtkWidget *menu_shell,
505 GtkSignalFunc activate_cb,
506 char *label,
507 const gchar *icon_name, // stock id or name for icon_load
508 // overridden by label, accels, icon_name
509 const gchar *accel_path,
510 guint accel_key, // from gdk/gdkkeysyms.h
511 GdkModifierType accel_mods, // e.g. GDK_CONTROL_MASK
512 gboolean enabled,
513 gboolean is_check, gboolean check_status)
514 {
515 GtkWidget *item = NULL;
516 GtkWidget *image = NULL;
517
518 gboolean stock_item_known = FALSE;
519 GtkStockItem stock_item;
520 if (icon_name != NULL) {
521 stock_item_known = gtk_stock_lookup(icon_name, &stock_item);
522 }
523
524 // Icons
525 #ifndef UISPECIFIC_MENU_HAS_ICONS
526 item = is_check ? gtk_check_menu_item_new_with_mnemonic (label)
527 : gtk_menu_item_new_with_mnemonic (label);
528 #else
529 if (is_check) {
530 item = gtk_check_menu_item_new_with_mnemonic (label);
531 }
532 else if (!stock_item_known) {
533 GdkPixbuf *pbuf = icon_load(&appdata->icon, icon_name);
534 if (pbuf) {
535 image = gtk_image_new_from_pixbuf(pbuf);
536 }
537 if (image) {
538 item = gtk_image_menu_item_new_with_mnemonic(label);
539 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
540 }
541 else {
542 item = gtk_menu_item_new_with_mnemonic(label);
543 }
544 }
545 else {
546 item = gtk_image_menu_item_new_with_mnemonic(label);
547 image = gtk_image_new_from_stock(icon_name, GTK_ICON_SIZE_MENU);
548 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
549 }
550 #endif
551
552 #ifdef UISPECIFIC_MENU_HAS_ACCELS
553 // Accelerators
554 // Default
555 if (accel_path != NULL) {
556 gtk_menu_item_set_accel_path(GTK_MENU_ITEM(item), accel_path);
557 if (accel_key != 0) {
558 gtk_accel_map_add_entry( accel_path, accel_key, accel_mods );
559 }
560 else if (stock_item_known) {
561 gtk_accel_map_add_entry( accel_path, stock_item.keyval,
562 stock_item.modifier );
563 }
564 }
565 #endif
566
567 gtk_menu_shell_append(GTK_MENU_SHELL(menu_shell), GTK_WIDGET(item));
568 gtk_widget_set_sensitive(GTK_WIDGET(item), enabled);
569 if (is_check)
570 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), check_status);
571
572 g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(activate_cb),
573 appdata);
574 return item;
575 }
576
577
578 void menu_create(appdata_t *appdata) {
579 GtkWidget *menu, *item, *submenu;
580 GtkWidget *about_quit_items_menu;
581
582 if (g_module_supported()) {
583 printf("*** can use GModule: consider using GtkUIManager / GtkBuilder\n");
584 }
585
586 menu = uispecific_main_menu_new();
587 about_quit_items_menu = menu;
588
589 /* -------------------- Project submenu -------------------- */
590
591 GtkAccelGroup *accel_grp = gtk_accel_group_new();
592 item = gtk_menu_item_new_with_mnemonic( _("_Project") );
593 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
594 submenu = gtk_menu_new();
595 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
596 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
597 #ifdef UISPECIFIC_MAIN_MENU_IS_MENU_BAR
598 about_quit_items_menu = submenu;
599 #endif
600
601 menu_append_new_item(
602 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_project_open), _("_Open..."),
603 GTK_STOCK_OPEN, "<OSM2Go-Main>/Project/Open",
604 0, 0, TRUE, FALSE, FALSE
605 );
606
607 appdata->menu_item_project_close = menu_append_new_item(
608 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_project_close), _("_Close"),
609 GTK_STOCK_CLOSE, "<OSM2Go-Main>/Project/Close",
610 0, 0, TRUE, FALSE, FALSE
611 );
612
613 /* --------------- view menu ------------------- */
614
615 #ifndef UISPECIFIC_MAIN_MENU_IS_MENU_BAR
616 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
617 #endif
618
619 appdata->menu_view = item = gtk_menu_item_new_with_mnemonic( _("_View") );
620 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
621 submenu = gtk_menu_new();
622 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
623 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
624
625 appdata->menu_item_view_fullscreen = menu_append_new_item(
626 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_fullscreen), _("_Fullscreen"),
627 GTK_STOCK_FULLSCREEN, "<OSM2Go-Main>/View/Fullscreen",
628 0, 0, TRUE, TRUE, FALSE
629 );
630
631 menu_append_new_item(
632 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_zoomin), _("Zoom _in"),
633 GTK_STOCK_ZOOM_IN, "<OSM2Go-Main>/View/ZoomIn",
634 GDK_comma, GDK_CONTROL_MASK, TRUE, FALSE, FALSE
635 );
636
637 menu_append_new_item(
638 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_zoomout), _("Zoom _out"),
639 GTK_STOCK_ZOOM_OUT, "<OSM2Go-Main>/View/ZoomOut",
640 GDK_period, GDK_CONTROL_MASK, TRUE, FALSE, FALSE
641 );
642
643 /* -------------------- OSM submenu -------------------- */
644
645 appdata->menu_osm = item = gtk_menu_item_new_with_mnemonic( _("_OSM") );
646 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
647 submenu = gtk_menu_new();
648 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
649 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
650
651 appdata->menu_item_osm_upload = menu_append_new_item(
652 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_upload), _("_Upload..."),
653 "upload.16", "<OSM2Go-Main>/OSM/Upload",
654 GDK_u, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
655 );
656
657 menu_append_new_item(
658 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_download), _("_Download..."),
659 "download.16", "<OSM2Go-Main>/OSM/Download",
660 GDK_d, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
661 );
662
663 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
664
665 if(getenv("OSM2GO_UNDO_TEST")) {
666 appdata->menu_item_osm_undo = menu_append_new_item(
667 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_undo), _("_Undo"),
668 GTK_STOCK_UNDO, "<OSM2Go-Main>/OSM/Undo",
669 GDK_z, GDK_CONTROL_MASK, TRUE, FALSE, FALSE
670 );
671 } else
672 printf("set environment variable OSM2GO_UNDO_TEST to enable undo framework tests\n");
673
674 appdata->menu_item_osm_save_changes = menu_append_new_item(
675 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_save_changes), _("_Save local changes"),
676 GTK_STOCK_SAVE, "<OSM2Go-Main>/OSM/SaveChanges",
677 GDK_s, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
678 );
679
680 appdata->menu_item_osm_undo_changes = menu_append_new_item(
681 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_undo_changes), _("Disca_rd local changes..."),
682 GTK_STOCK_DELETE, "<OSM2Go-Main>/OSM/DiscardChanges",
683 0, 0, TRUE, FALSE, FALSE
684 );
685
686 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
687 appdata->menu_item_osm_relations = menu_append_new_item(
688 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_osm_relations), _("_Relations..."),
689 NULL, "<OSM2Go-Main>/OSM/Relations",
690 GDK_r, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
691 );
692
693 /* -------------------- wms submenu -------------------- */
694
695 appdata->menu_wms = item = gtk_menu_item_new_with_mnemonic( _("_WMS") );
696 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
697 submenu = gtk_menu_new();
698 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
699 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
700
701 menu_append_new_item(
702 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_import), _("_Import..."),
703 GTK_STOCK_INDEX, "<OSM2Go-Main>/WMS/Import",
704 0, 0, TRUE, FALSE, FALSE
705 );
706
707 appdata->menu_item_wms_clear = menu_append_new_item(
708 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_clear), _("_Clear"),
709 GTK_STOCK_CLEAR, "<OSM2Go-Main>/WMS/Clear",
710 0, 0, TRUE, FALSE, FALSE
711 );
712 gtk_widget_set_sensitive(appdata->menu_item_wms_clear, FALSE);
713
714 appdata->menu_item_wms_adjust = menu_append_new_item(
715 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_adjust), _("_Adjust"),
716 NULL, "<OSM2Go-Main>/WMS/Adjust",
717 0, 0, TRUE, FALSE, FALSE
718 );
719 gtk_widget_set_sensitive(appdata->menu_item_wms_adjust, FALSE);
720
721 /* -------------------- map submenu -------------------- */
722
723 appdata->menu_map = item = gtk_menu_item_new_with_mnemonic( _("_Map") );
724 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
725 submenu = gtk_menu_new();
726 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
727 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
728
729 appdata->menu_item_map_hide_sel = menu_append_new_item(
730 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_hide_sel), _("_Hide selected"),
731 GTK_STOCK_REMOVE, "<OSM2Go-Main>/Map/HideSelected",
732 0, 0, TRUE, FALSE, FALSE
733 );
734 gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, FALSE);
735
736 appdata->menu_item_map_show_all = menu_append_new_item(
737 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_show_all), _("_Show all"),
738 GTK_STOCK_ADD, "<OSM2Go-Main>/Map/ShowAll",
739 0, 0, TRUE, FALSE, FALSE
740 );
741 gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);
742
743 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
744
745 menu_append_new_item(
746 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_style), _("St_yle..."),
747 GTK_STOCK_SELECT_COLOR, "<OSM2Go-Main>/Map/Style",
748 0, 0, TRUE, FALSE, FALSE
749 );
750
751 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
752
753 /* switches mainly intended for testing/debugging */
754 menu_append_new_item(
755 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_redraw), _("_Redraw"),
756 NULL, "<OSM2Go-Main>/Map/Redraw",
757 GDK_r, GDK_CONTROL_MASK, TRUE, FALSE, FALSE
758 );
759
760 appdata->menu_item_map_no_icons = menu_append_new_item(
761 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_no_icons), _("No _icons"),
762 NULL, "<OSM2Go-Main>/Map/NoIcons",
763 0, 0, TRUE, TRUE, appdata->settings->no_icons
764 );
765
766 appdata->menu_item_map_no_antialias = menu_append_new_item(
767 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_no_antialias),
768 _("No _antialias"),
769 NULL, "<OSM2Go-Main>/Map/NoAntialias",
770 0, 0, TRUE, TRUE, appdata->settings->no_antialias
771 );
772
773 /* -------------------- track submenu -------------------- */
774
775 appdata->track.menu_track = item = gtk_menu_item_new_with_mnemonic(_("_Track"));
776 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
777 submenu = gtk_menu_new();
778 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
779 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
780
781 appdata->track.menu_item_import = menu_append_new_item(
782 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_import), _("_Import..."),
783 NULL, "<OSM2Go-Main>/Track/Import",
784 0, 0, TRUE, FALSE, FALSE
785 );
786
787 appdata->track.menu_item_export = menu_append_new_item(
788 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_export), _("_Export..."),
789 NULL, "<OSM2Go-Main>/Track/Export",
790 0, 0, FALSE, FALSE, FALSE
791 );
792
793 appdata->track.menu_item_clear = menu_append_new_item(
794 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_clear), _("_Clear"),
795 GTK_STOCK_CLEAR, "<OSM2Go-Main>/Track/Clear",
796 0, 0, FALSE, FALSE, FALSE
797 );
798
799
800 appdata->track.menu_item_enable_gps = menu_append_new_item(
801 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_enable_gps),_("_GPS enable"),
802 NULL, "<OSM2Go-Main>/Track/GPS",
803 GDK_g, GDK_CONTROL_MASK|GDK_SHIFT_MASK, TRUE, TRUE,
804 appdata->settings->enable_gps
805 );
806
807 appdata->track.menu_item_follow_gps = menu_append_new_item(
808 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_follow_gps), _("GPS follow"),
809 NULL, "<OSM2Go-Main>/Track/Follow",
810 0, 0, appdata->settings->enable_gps, TRUE,
811 appdata->settings->follow_gps
812 );
813
814 /* ------------------------------------------------------- */
815
816 gtk_menu_shell_append(GTK_MENU_SHELL(about_quit_items_menu),
817 gtk_separator_menu_item_new());
818
819 menu_append_new_item(
820 appdata, about_quit_items_menu, GTK_SIGNAL_FUNC(cb_menu_about), _("_About..."),
821 GTK_STOCK_ABOUT, "<OSM2Go-Main>/About",
822 0, 0, TRUE, FALSE, FALSE
823 );
824
825 menu_append_new_item(
826 appdata, about_quit_items_menu, GTK_SIGNAL_FUNC(cb_menu_quit), _("_Quit"),
827 GTK_STOCK_QUIT, "<OSM2Go-Main>/Quit",
828 0, 0, TRUE, FALSE, FALSE
829 );
830
831 gtk_window_add_accel_group(GTK_WINDOW(appdata->window), accel_grp);
832
833 #ifdef USE_HILDON
834 hildon_window_set_menu(appdata->window, GTK_MENU(menu));
835 #else
836 GtkWidget *menu_bar = menu;
837
838 #ifndef UISPECIFIC_MAIN_MENU_IS_MENU_BAR
839 // we need to make one first
840 menu_bar = gtk_menu_bar_new();
841
842 GtkWidget *root_menu = gtk_menu_item_new_with_label (_("Menu"));
843 gtk_widget_show(root_menu);
844
845 gtk_menu_bar_append(menu_bar, root_menu);
846 gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
847
848 gtk_widget_show(menu_bar);
849 #endif //UISPECIFIC_MAIN_MENU_IS_MENU_BAR
850
851 gtk_box_pack_start(GTK_BOX(appdata->vbox), menu_bar, 0, 0, 0);
852
853 #endif //USE_HILDON
854 }
855
856 /********************* end of menu **********************/
857
858 #ifdef UISPECIFIC_MENU_HAS_ACCELS
859 #define ACCELS_FILE "accels"
860
861 static void menu_accels_load(appdata_t *appdata) {
862 char *accels_file = g_strdup_printf("%s/" ACCELS_FILE,
863 appdata->settings->base_path);
864 gtk_accel_map_load(accels_file);
865 g_free(accels_file);
866 }
867
868 static void menu_accels_save(appdata_t *appdata) {
869 char *accels_file = g_strdup_printf("%s" ACCELS_FILE,
870 appdata->settings->base_path);
871 gtk_accel_map_save(accels_file);
872 g_free(accels_file);
873 }
874
875 #endif
876
877
878 void cleanup(appdata_t *appdata) {
879 #ifdef UISPECIFIC_MENU_HAS_ACCELS
880 menu_accels_save(appdata);
881 #endif
882
883 settings_save(appdata->settings);
884
885 #ifdef USE_HILDON
886 if(appdata->osso_context)
887 osso_deinitialize(appdata->osso_context);
888
889 appdata->program = NULL;
890 #endif
891
892 printf("waiting for gtk to shut down ");
893
894 /* let gtk clean up first */
895 while(gtk_events_pending()) {
896 putchar('.');
897 gtk_main_iteration();
898 }
899
900 printf(" ok\n");
901
902 /* save project file */
903 if(appdata->project)
904 project_save(GTK_WIDGET(appdata->window), appdata->project);
905
906 map_remove_bg_image(appdata->map);
907
908 osm_free(&appdata->icon, appdata->osm);
909
910 curl_global_cleanup();
911
912 josm_presets_free(appdata->presets);
913
914 icon_free_all(&appdata->icon);
915
916 gps_release(appdata);
917
918 settings_free(appdata->settings);
919
920 statusbar_free(appdata->statusbar);
921
922 iconbar_free(appdata->iconbar);
923
924 project_free(appdata->project);
925
926 if(appdata->menu_item_osm_undo)
927 undo_free(appdata->undo.state);
928
929 puts("everything is gone");
930 }
931
932 void on_window_destroy (GtkWidget *widget, gpointer data) {
933 appdata_t *appdata = (appdata_t*)data;
934
935 gtk_main_quit();
936 appdata->window = NULL;
937 }
938
939 gboolean on_window_key_press(GtkWidget *widget,
940 GdkEventKey *event, gpointer data) {
941 appdata_t *appdata = (appdata_t*)data;
942 int handled = FALSE;
943
944 // the map handles some keys on its own ...
945 switch(event->keyval) {
946
947 #ifdef USE_HILDON
948 /* this is in fact a mapping to GDK_F6 */
949 case HILDON_HARDKEY_FULLSCREEN:
950 #else
951 case GDK_F11:
952 #endif
953 if(!gtk_check_menu_item_get_active(
954 GTK_CHECK_MENU_ITEM(appdata->menu_item_view_fullscreen))) {
955 gtk_window_fullscreen(GTK_WINDOW(appdata->window));
956 gtk_check_menu_item_set_active(
957 GTK_CHECK_MENU_ITEM(appdata->menu_item_view_fullscreen), TRUE);
958 } else {
959 gtk_window_unfullscreen(GTK_WINDOW(appdata->window));
960 gtk_check_menu_item_set_active(
961 GTK_CHECK_MENU_ITEM(appdata->menu_item_view_fullscreen), FALSE);
962 }
963
964 handled = TRUE;
965 break;
966 }
967
968 /* forward unprocessed key presses to map */
969 if(!handled && appdata->project && appdata->osm)
970 handled = map_key_press_event(appdata, event);
971
972 return handled;
973 }
974
975 int main(int argc, char *argv[]) {
976 appdata_t appdata;
977
978 /* init appdata */
979 memset(&appdata, 0, sizeof(appdata));
980
981 printf("Using locale for %s in %s\n", PACKAGE, LOCALEDIR);
982
983 setlocale(LC_ALL, "");
984 bindtextdomain(PACKAGE, LOCALEDIR);
985 bind_textdomain_codeset(PACKAGE, "UTF-8");
986 textdomain(PACKAGE);
987
988 /* Must initialize libcurl before any threads are started */
989 curl_global_init(CURL_GLOBAL_ALL);
990
991 g_thread_init(NULL);
992
993 gtk_init (&argc, &argv);
994
995 gps_init(&appdata);
996
997 #ifdef USE_HILDON
998 printf("Installing osso context for \"org.harbaum." PACKAGE "\"\n");
999 appdata.osso_context = osso_initialize("org.harbaum."PACKAGE,
1000 VERSION, TRUE, NULL);
1001 if(appdata.osso_context == NULL)
1002 fprintf(stderr, "error initiating osso context\n");
1003
1004 dbus_register(&appdata);
1005 #endif
1006
1007 #ifdef USE_HILDON
1008 /* Create the hildon program and setup the title */
1009 appdata.program = HILDON_PROGRAM(hildon_program_get_instance());
1010 g_set_application_name("OSM2Go");
1011
1012 /* Create HildonWindow and set it to HildonProgram */
1013 appdata.window = HILDON_WINDOW(hildon_window_new());
1014 hildon_program_add_window(appdata.program, appdata.window);
1015 #else
1016 /* Create a Window. */
1017 appdata.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1018 gtk_window_set_title(GTK_WINDOW(appdata.window), "OSM2Go");
1019 /* Set a decent default size for the window. */
1020 gtk_window_set_default_size(GTK_WINDOW(appdata.window),
1021 DEFAULT_WIDTH, DEFAULT_HEIGHT);
1022 gtk_window_set_icon(GTK_WINDOW(appdata.window),
1023 icon_load(&appdata.icon, PACKAGE));
1024 #endif
1025
1026 g_signal_connect(G_OBJECT(appdata.window), "destroy",
1027 G_CALLBACK(on_window_destroy), &appdata);
1028
1029 g_signal_connect(G_OBJECT(appdata.window), "key_press_event",
1030 G_CALLBACK(on_window_key_press), &appdata);
1031
1032 /* user specific init */
1033 appdata.settings = settings_load();
1034
1035 appdata.vbox = gtk_vbox_new(FALSE,0);
1036 menu_create(&appdata);
1037 #ifdef UISPECIFIC_MENU_HAS_ACCELS
1038 menu_accels_load(&appdata);
1039 #endif
1040
1041 /* ----------------------- setup main window ---------------- */
1042
1043 GtkWidget *hbox = gtk_hbox_new(FALSE,0);
1044 GtkWidget *vbox = gtk_vbox_new(FALSE,0);
1045
1046 #ifdef PORTRAIT
1047 gtk_box_pack_start(GTK_BOX(vbox), iconbar_new(&appdata), FALSE, FALSE, 0);
1048 #endif
1049
1050 /* generate main map view */
1051 GtkWidget *map = map_new(&appdata);
1052 if(!map) {
1053 cleanup(&appdata);
1054 return -1;
1055 }
1056
1057 gtk_box_pack_start(GTK_BOX(vbox), map, TRUE, TRUE, 0);
1058 gtk_box_pack_start(GTK_BOX(vbox), statusbar_new(&appdata), FALSE, FALSE, 0);
1059
1060 #ifndef PORTRAIT
1061 gtk_box_pack_start(GTK_BOX(hbox), iconbar_new(&appdata), FALSE, FALSE, 0);
1062 #endif
1063 gtk_box_pack_start(GTK_BOX(hbox), gtk_vseparator_new(), FALSE, FALSE, 0);
1064 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1065
1066 gtk_box_pack_start(GTK_BOX(appdata.vbox), hbox, TRUE, TRUE, 0);
1067
1068 gtk_container_add(GTK_CONTAINER(appdata.window), appdata.vbox);
1069
1070 gtk_widget_show_all(GTK_WIDGET(appdata.window));
1071
1072 appdata.presets = josm_presets_load();
1073
1074 /* let gtk do its thing before loading the data, */
1075 /* so the user sees something */
1076 while(gtk_events_pending()) {
1077 putchar('.');
1078 gtk_main_iteration();
1079 }
1080
1081 /* load project if one is specified in the settings */
1082 if(appdata.settings->project)
1083 project_load(&appdata, appdata.settings->project);
1084
1085 main_ui_enable(&appdata);
1086
1087 /* start GPS if enabled by config */
1088 if(appdata.settings && appdata.settings->enable_gps)
1089 track_enable_gps(&appdata, TRUE);
1090
1091 /* ------------ jump into main loop ---------------- */
1092
1093 gtk_main();
1094
1095 puts("gtk_main() left");
1096
1097 track_save(appdata.project, appdata.track.track);
1098 track_clear(&appdata, appdata.track.track);
1099 appdata.track.track = NULL;
1100
1101 /* save a diff if there are dirty entries */
1102 diff_save(appdata.project, appdata.osm);
1103
1104 cleanup(&appdata);
1105
1106 return 0;
1107 }
1108
1109 // vim:et:ts=8:sw=2:sts=2:ai