Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


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