Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


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