Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 64 - (hide 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 harbaum 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 harbaum 22 #include <gdk/gdkkeysyms.h>
23 harbaum 1
24     #include "appdata.h"
25 achadwick 28 #include "banner.h"
26 harbaum 1
27     /* disable/enable main screen control dependant on presence of open project */
28 harbaum 4 static void main_ui_enable(appdata_t *appdata) {
29     gboolean project_valid = (appdata->project != NULL);
30     gboolean osm_valid = (appdata->osm != NULL);
31 harbaum 1
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 harbaum 4 if(project_valid)
40 harbaum 1 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 harbaum 4 if(project_valid)
48 harbaum 1 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 harbaum 4 gtk_widget_set_sensitive(appdata->iconbar->toolbar, osm_valid);
55 harbaum 1
56     /* disable all menu entries related to map */
57 harbaum 4 gtk_widget_set_sensitive(appdata->menu_osm, project_valid);
58     gtk_widget_set_sensitive(appdata->menu_item_osm_upload, osm_valid);
59 harbaum 64 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 harbaum 15 gtk_widget_set_sensitive(appdata->menu_item_osm_undo_changes, osm_valid);
62 harbaum 4 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 harbaum 1
68 harbaum 4 if(!project_valid)
69 achadwick 6 statusbar_set(appdata, _("Please load or create a project"), FALSE);
70 harbaum 1 }
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 harbaum 4 main_ui_enable(appdata);
79 harbaum 1 }
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 harbaum 4 main_ui_enable(appdata);
86 harbaum 1 }
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 achadwick 28 "Andrew Chadwick <andrewc-osm2go@piffle.org>",
99 harbaum 1 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 harbaum 4 if(!appdata->project) return;
134 harbaum 1
135 harbaum 4 /* 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 harbaum 1
142 harbaum 4 appdata->osm = NULL;
143     }
144    
145 harbaum 1 // download
146 harbaum 4 if(osm_download(GTK_WIDGET(appdata->window), appdata->project)) {
147 achadwick 36 banner_busy_start(appdata, 1, "Redrawing...");
148 harbaum 4 appdata->osm = osm_parse(appdata->project->osm);
149     diff_restore(appdata, appdata->project, appdata->osm);
150     map_paint(appdata);
151 achadwick 36 banner_busy_stop(appdata); //"Redrawing..."
152 harbaum 4 }
153 harbaum 1
154 harbaum 4 main_ui_enable(appdata);
155 harbaum 1 }
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 harbaum 14 /* ---------------------------------------------------------- */
190 harbaum 1
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 achadwick 28 banner_busy_start(appdata, 1, "Redrawing...");
198 harbaum 1 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 achadwick 28 banner_busy_stop(appdata); //"Redrawing..."
213 harbaum 1 }
214     #endif
215    
216     static void
217 harbaum 14 cb_menu_style(GtkWidget *widget, gpointer data) {
218 harbaum 1 appdata_t *appdata = (appdata_t*)data;
219    
220     style_select(GTK_WIDGET(appdata->window), appdata);
221     }
222    
223     static void
224 harbaum 14 cb_menu_map_no_icons(GtkWidget *widget, gpointer data) {
225 harbaum 1 appdata_t *appdata = (appdata_t*)data;
226    
227 achadwick 28 banner_busy_start(appdata, 1, "Redrawing...");
228 harbaum 14 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 achadwick 28 banner_busy_stop(appdata); //"Redrawing..."
233 harbaum 14 }
234    
235     static void
236 harbaum 24 cb_menu_map_no_antialias(GtkWidget *widget, gpointer data) {
237     appdata_t *appdata = (appdata_t*)data;
238    
239 achadwick 28 banner_busy_start(appdata, 1, "Redrawing...");
240 harbaum 24 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 achadwick 28 banner_busy_stop(appdata); //"Redrawing..."
245 harbaum 24 }
246    
247     static void
248 harbaum 64 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 harbaum 14 cb_menu_save_changes(GtkWidget *widget, gpointer data) {
258     appdata_t *appdata = (appdata_t*)data;
259    
260 harbaum 1 diff_save(appdata->project, appdata->osm);
261 achadwick 28 banner_show_info(appdata, _("Saved local changes"));
262 harbaum 1 }
263    
264 harbaum 15 static void
265     cb_menu_undo_changes(GtkWidget *widget, gpointer data) {
266     appdata_t *appdata = (appdata_t*)data;
267 harbaum 1
268 harbaum 15 if(!yes_no_f(GTK_WIDGET(appdata->window), NULL, 0, 0,
269 achadwick 28 _("Discard local changes?"),
270     _("Throw away all the changes you've not uploaded yet? This can't be undone.")))
271 harbaum 15 return;
272 achadwick 28
273     banner_busy_start(appdata, 1, _("Redrawing..."));
274 harbaum 15 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 achadwick 28 banner_busy_stop(appdata); //"Redrawing..."
280 harbaum 15
281 achadwick 28 banner_show_info(appdata, _("Discarded local changes"));
282 harbaum 15 }
283    
284 harbaum 1 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 achadwick 55
385    
386    
387     /*
388     * Platform-specific UI tweaks.
389     */
390    
391    
392 achadwick 37 #ifndef USE_HILDON
393     #ifdef PORTRAIT
394 achadwick 55
395     // Portrait mode, for openmoko-like systems
396     #define uispecific_main_menu_new gtk_menu_new
397    
398 achadwick 37 #else
399 achadwick 55
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 achadwick 37 #endif //PORTRAIT
407 achadwick 55 #else//USE_HILDON
408    
409     // Maemo/Hildon builds
410     #define uispecific_main_menu_new gtk_menu_new
411    
412 achadwick 37 #endif
413    
414 achadwick 55
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 harbaum 1 void menu_create(appdata_t *appdata) {
479     GtkWidget *menu, *item, *submenu;
480 achadwick 37 GtkWidget *about_quit_items_menu;
481 achadwick 55
482     if (g_module_supported()) {
483     printf("*** can use GModule: consider using GtkUIManager / GtkBuilder\n");
484     }
485    
486     menu = uispecific_main_menu_new();
487 achadwick 37 about_quit_items_menu = menu;
488 harbaum 1
489     /* -------------------- Project submenu -------------------- */
490    
491 achadwick 55 GtkAccelGroup *accel_grp = gtk_accel_group_new();
492     item = gtk_menu_item_new_with_mnemonic( _("_Project") );
493 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
494 harbaum 1 submenu = gtk_menu_new();
495 achadwick 55 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
496 harbaum 1 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
497 achadwick 55 #ifdef UISPECIFIC_MAIN_MENU_IS_MENU_BAR
498 achadwick 37 about_quit_items_menu = submenu;
499     #endif
500 harbaum 1
501 achadwick 55 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 harbaum 1
507 achadwick 55 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 harbaum 1
513     /* --------------- view menu ------------------- */
514    
515 achadwick 55 #ifndef UISPECIFIC_MENU_IS_MENU_BAR
516 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
517     #endif
518 harbaum 1
519 achadwick 55 appdata->menu_view = item = gtk_menu_item_new_with_mnemonic( _("_View") );
520 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
521 harbaum 1 submenu = gtk_menu_new();
522 achadwick 55 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
523 harbaum 1 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
524    
525 achadwick 55 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 harbaum 1
531 achadwick 55 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 harbaum 1
537 achadwick 55 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 harbaum 1
543     /* -------------------- OSM submenu -------------------- */
544    
545 achadwick 55 appdata->menu_osm = item = gtk_menu_item_new_with_mnemonic( _("_OSM") );
546 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
547 harbaum 1 submenu = gtk_menu_new();
548 achadwick 55 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
549 harbaum 1 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
550    
551 achadwick 55 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 harbaum 1
557 achadwick 55 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 harbaum 1
563 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
564 harbaum 1
565 harbaum 64 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 harbaum 1
574 harbaum 64 appdata->menu_item_osm_save_changes = menu_append_new_item(
575 achadwick 55 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 harbaum 15
580 achadwick 55 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 harbaum 1 /* -------------------- wms submenu -------------------- */
587    
588 achadwick 55 appdata->menu_wms = item = gtk_menu_item_new_with_mnemonic( _("_WMS") );
589 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
590 harbaum 1 submenu = gtk_menu_new();
591 achadwick 55 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
592 harbaum 1 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
593    
594 achadwick 55 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 harbaum 1
600 achadwick 55 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 harbaum 1
607 achadwick 55 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 harbaum 1
614     /* -------------------- map submenu -------------------- */
615    
616 achadwick 55 appdata->menu_map = item = gtk_menu_item_new_with_mnemonic( _("_Map") );
617 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
618 harbaum 1 submenu = gtk_menu_new();
619 achadwick 55 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
620 harbaum 1 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
621    
622 achadwick 55 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 harbaum 1
629 achadwick 55 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 harbaum 1
636 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
637 harbaum 1
638 achadwick 55 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 harbaum 1
644 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
645 harbaum 1
646 harbaum 24 /* switches mainly intended for testing/debugging */
647 achadwick 55 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 harbaum 1
653 achadwick 55 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 harbaum 14
659 achadwick 55 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 harbaum 24
666 harbaum 1 /* -------------------- track submenu -------------------- */
667    
668 achadwick 55 appdata->track.menu_track = item = gtk_menu_item_new_with_mnemonic(_("_Track"));
669 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
670 harbaum 1 submenu = gtk_menu_new();
671 achadwick 55 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
672 harbaum 1 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
673    
674 achadwick 55 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 harbaum 1
680 achadwick 55 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 harbaum 1
686 achadwick 55 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 harbaum 1
692 achadwick 55
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 harbaum 1
699     /* ------------------------------------------------------- */
700    
701 achadwick 37 gtk_menu_shell_append(GTK_MENU_SHELL(about_quit_items_menu),
702     gtk_separator_menu_item_new());
703 harbaum 1
704 achadwick 55 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 harbaum 1
710 achadwick 55 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 harbaum 1
716 achadwick 55 gtk_window_add_accel_group(GTK_WINDOW(appdata->window), accel_grp);
717    
718 harbaum 1 #ifdef USE_HILDON
719     hildon_window_set_menu(appdata->window, GTK_MENU(menu));
720     #else
721 achadwick 37 GtkWidget *menu_bar = menu;
722 harbaum 1
723 achadwick 55 #ifndef UISPECIFIC_MAIN_MENU_IS_MENU_BAR
724 achadwick 37 // we need to make one first
725     menu_bar = gtk_menu_bar_new();
726    
727 harbaum 1 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 achadwick 55 #endif //UISPECIFIC_MAIN_MENU_IS_MENU_BAR
735 achadwick 37
736 harbaum 1 gtk_box_pack_start(GTK_BOX(appdata->vbox), menu_bar, 0, 0, 0);
737 achadwick 37
738     #endif //USE_HILDON
739 harbaum 1 }
740    
741     /********************* end of menu **********************/
742    
743 achadwick 55 #ifdef UISPECIFIC_MENU_HAS_ACCELS
744     #define ACCELS_FILE "accels"
745 harbaum 1
746 achadwick 55 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 harbaum 1 void cleanup(appdata_t *appdata) {
764 achadwick 55 #ifdef UISPECIFIC_MENU_HAS_ACCELS
765     menu_accels_save(appdata);
766     #endif
767    
768 harbaum 1 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 harbaum 54 undo_free(appdata->undo_state);
812    
813 harbaum 1 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 harbaum 22 #ifdef USE_HILDON
832     /* this is in fact a mapping to GDK_F6 */
833 harbaum 1 case HILDON_HARDKEY_FULLSCREEN:
834 harbaum 22 #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 harbaum 1 gtk_check_menu_item_set_active(
841 harbaum 22 GTK_CHECK_MENU_ITEM(appdata->menu_item_view_fullscreen), TRUE);
842     } else {
843 harbaum 1 gtk_window_unfullscreen(GTK_WINDOW(appdata->window));
844 harbaum 22 gtk_check_menu_item_set_active(
845     GTK_CHECK_MENU_ITEM(appdata->menu_item_view_fullscreen), FALSE);
846     }
847    
848     handled = TRUE;
849 harbaum 1 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 harbaum 14 /* user specific init */
917     appdata.settings = settings_load();
918    
919 harbaum 1 appdata.vbox = gtk_vbox_new(FALSE,0);
920     menu_create(&appdata);
921 achadwick 55 #ifdef UISPECIFIC_MENU_HAS_ACCELS
922     menu_accels_load(&appdata);
923     #endif
924 harbaum 1
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 harbaum 22
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 harbaum 1 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 harbaum 4 main_ui_enable(&appdata);
970 harbaum 1
971     /* ------------ jump into main loop ---------------- */
972    
973     gtk_main();
974    
975 harbaum 4 puts("gtk_main() left");
976    
977 harbaum 1 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 achadwick 55
987     // vim:et:ts=8:sw=2:sts=2:ai