Diff of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 101 by achadwick, Sat Feb 28 22:31:10 2009 UTC revision 281 by harbaum, Fri Sep 4 07:51:58 2009 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.   * Copyright (C) 2008-2009 Till Harbaum <till@harbaum.org>.
3   *   *
4   * This file is part of OSM2Go.   * This file is part of OSM2Go.
5   *   *
# Line 23  Line 23 
23  #include <curl/curl.h>  #include <curl/curl.h>
24  #include <gdk/gdkkeysyms.h>  #include <gdk/gdkkeysyms.h>
25    
26    #if defined(USE_HILDON) && (MAEMO_VERSION_MAJOR == 5)
27    #define FREMANTLE
28    #include <hildon/hildon-button.h>
29    #include <hildon/hildon-check-button.h>
30    #include <hildon/hildon-window-stack.h>
31    #include <gdk/gdkx.h>
32    #include <X11/Xatom.h>
33    #endif
34    
35  #include "appdata.h"  #include "appdata.h"
36  #include "banner.h"  #include "banner.h"
37    
38  /* disable/enable main screen control dependant on presence of open project */  /* disable/enable main screen control dependant on presence of open project */
39  static void main_ui_enable(appdata_t *appdata) {  void main_ui_enable(appdata_t *appdata) {
40    gboolean project_valid = (appdata->project != NULL);    gboolean project_valid = (appdata->project != NULL);
41    gboolean osm_valid = (appdata->osm != NULL);    gboolean osm_valid = (appdata->osm != NULL);
42    
# Line 36  static void main_ui_enable(appdata_t *ap Line 45  static void main_ui_enable(appdata_t *ap
45      map_action_cancel(appdata);      map_action_cancel(appdata);
46    
47    /* ---- set project name as window title ----- */    /* ---- set project name as window title ----- */
48  #ifndef USE_HILDON  #if defined(USE_HILDON) && MAEMO_VERSION_MAJOR < 5
49      if(project_valid)
50        gtk_window_set_title(GTK_WINDOW(appdata->window), appdata->project->name);
51      else
52        gtk_window_set_title(GTK_WINDOW(appdata->window), "");
53    #else
54    char *str = NULL;    char *str = NULL;
55    #ifdef USE_HILDON
56      if(project_valid)
57        str = g_markup_printf_escaped("<b>%s</b> - OSM2Go",
58                                      appdata->project->name);
59      else
60        str = g_markup_printf_escaped("OSM2Go");
61    
62      hildon_window_set_markup(HILDON_WINDOW(appdata->window), str);
63    #else
64    if(project_valid)    if(project_valid)
65      str = g_strdup_printf("OSM2Go - %s", appdata->project->name);      str = g_strdup_printf("%s - OSM2Go", appdata->project->name);
66    else    else
67      str = g_strdup_printf("OSM2Go");      str = g_strdup_printf("OSM2Go");
68    
69    gtk_window_set_title(GTK_WINDOW(appdata->window), str);    gtk_window_set_title(GTK_WINDOW(appdata->window), str);
70    #endif
71    g_free(str);    g_free(str);
 #else  
   if(project_valid)  
     gtk_window_set_title(GTK_WINDOW(appdata->window), appdata->project->name);  
   else  
     gtk_window_set_title(GTK_WINDOW(appdata->window), "");  
72  #endif  #endif
73    
74    if(appdata->iconbar && appdata->iconbar->toolbar)    if(appdata->iconbar && appdata->iconbar->toolbar)
75      gtk_widget_set_sensitive(appdata->iconbar->toolbar, osm_valid);      gtk_widget_set_sensitive(appdata->iconbar->toolbar, osm_valid);
   
76    /* disable all menu entries related to map */    /* disable all menu entries related to map */
77    gtk_widget_set_sensitive(appdata->menu_osm, project_valid);    gtk_widget_set_sensitive(appdata->submenu_map, project_valid);
78    gtk_widget_set_sensitive(appdata->menu_item_osm_upload, osm_valid);    gtk_widget_set_sensitive(appdata->menu_item_map_upload, osm_valid);
79    if(appdata->menu_item_osm_undo)    if(appdata->menu_item_map_undo)
80      gtk_widget_set_sensitive(appdata->menu_item_osm_undo, osm_valid);      gtk_widget_set_sensitive(appdata->menu_item_map_undo, osm_valid);
81    gtk_widget_set_sensitive(appdata->menu_item_osm_save_changes, osm_valid);    if(appdata->menu_item_map_save_changes)
82    gtk_widget_set_sensitive(appdata->menu_item_osm_undo_changes, osm_valid);      gtk_widget_set_sensitive(appdata->menu_item_map_save_changes, osm_valid);
83    gtk_widget_set_sensitive(appdata->track.menu_track, osm_valid);    gtk_widget_set_sensitive(appdata->menu_item_map_undo_changes, osm_valid);
84    gtk_widget_set_sensitive(appdata->menu_view, osm_valid);    gtk_widget_set_sensitive(appdata->menu_item_map_relations, osm_valid);
85    gtk_widget_set_sensitive(appdata->menu_wms, osm_valid);    gtk_widget_set_sensitive(appdata->track.submenu_track, osm_valid);
86    gtk_widget_set_sensitive(appdata->menu_map, osm_valid);    gtk_widget_set_sensitive(appdata->submenu_view, osm_valid);
87    gtk_widget_set_sensitive(appdata->menu_item_project_close, project_valid);    gtk_widget_set_sensitive(appdata->submenu_wms, osm_valid);
88    
89    #ifdef ZOOM_BUTTONS
90      gtk_widget_set_sensitive(appdata->btn_zoom_in, osm_valid);
91      gtk_widget_set_sensitive(appdata->btn_zoom_out, osm_valid);
92    #endif
93    
94    if(!project_valid)    if(!project_valid)
95      statusbar_set(appdata, _("Please load or create a project"), FALSE);      statusbar_set(appdata, _("Please load or create a project"), FALSE);
# Line 75  static void main_ui_enable(appdata_t *ap Line 98  static void main_ui_enable(appdata_t *ap
98  /******************** begin of menu *********************/  /******************** begin of menu *********************/
99    
100  static void  static void
101  cb_menu_project_open(GtkWidget *window, gpointer data) {  cb_menu_project_open(GtkMenuItem *item, gpointer data) {
102    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
103    project_load(appdata, NULL);    project_load(appdata, NULL);
104    main_ui_enable(appdata);    main_ui_enable(appdata);
105  }  }
106    
107  static void  static void
108  cb_menu_project_close(GtkWidget *window, gpointer data) {  cb_menu_project_wizard(GtkMenuItem *item, gpointer data) {
109    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
110    project_close(appdata);    project_wizard(appdata);
   main_ui_enable(appdata);  
111  }  }
112    
113  static void  typedef struct {
114  cb_menu_about(GtkWidget *window, gpointer data) {    appdata_t *appdata;
115    GtkAboutDialog *about = GTK_ABOUT_DIALOG(gtk_about_dialog_new());    GtkWidget *dialog;
116    } about_context_t;
117    
118    #ifdef ENABLE_BROWSER_INTERFACE
119    #ifndef USE_HILDON
120    #include <libgnome/gnome-url.h>
121    #else
122    #include <tablet-browser-interface.h>
123    #endif
124    
125    gtk_about_dialog_set_name(about, "OSM2Go");  void on_paypal_button_clicked(GtkButton *button, about_context_t *context) {
126    gtk_about_dialog_set_version(about, VERSION);    const char *url =
127    gtk_about_dialog_set_copyright(about, _("Copyright 2008"));      "https://www.paypal.com/cgi-bin/webscr"
128        "?cmd=_s-xclick&hosted_button_id=7439286";
129    
130    #ifndef USE_HILDON
131      /* taken from gnome-open, part of libgnome */
132      GError *err = NULL;
133      gnome_url_show(url, &err);
134    #else
135      /* close the dialog on hildon as it doesn't like open dialogs */
136      gtk_dialog_response(GTK_DIALOG(context->dialog), GTK_RESPONSE_ACCEPT);
137    
138      osso_rpc_run_with_defaults(context->appdata->osso_context, "osso_browser",
139                                 OSSO_BROWSER_OPEN_NEW_WINDOW_REQ, NULL,
140                                 DBUS_TYPE_STRING, url,
141                                 DBUS_TYPE_BOOLEAN, FALSE, DBUS_TYPE_INVALID);
142    #endif
143    }
144    #endif
145    
146    static void
147    cb_menu_about(GtkMenuItem *item, gpointer data) {
148      about_context_t context;
149      context.appdata = (appdata_t *)data;
150    
151    const gchar *authors[] = {    const gchar *authors[] = {
152      "Till Harbaum <till@harbaum.org>",      "Till Harbaum <till@harbaum.org>",
153      "Andrew Chadwick <andrewc-osm2go@piffle.org>",      "Andrew Chadwick <andrewc-osm2go@piffle.org>",
154        "Marcus Bauer <marcus.bauer@gmail.com>",
155        "John Stowers <john.stowers@gmail.com>",
156        NULL };
157    
158      const gchar *artists[] = {
159        "Andrew Zhilin <drew.zhilin@gmail.com>",
160      NULL };      NULL };
161    
162    gtk_about_dialog_set_authors(about, authors);    context.dialog = g_object_new(GTK_TYPE_ABOUT_DIALOG,
163                            "name", "OSM2Go",
164                            "version", VERSION,
165                            "copyright", _("Copyright 2008-2009"),
166                            "authors", authors,
167                            "artists", artists,
168                            "website", _("http://www.harbaum.org/till/maemo"),
169                            "comments", _("Mobile OSM Editor"),
170                            NULL);
171    
172    gtk_about_dialog_set_website(about,  #ifdef ENABLE_BROWSER_INTERFACE
173         _("http://www.harbaum.org/till/maemo"));    /* add a way to donate to the project */
174      GtkWidget *alignment = gtk_alignment_new(0.5, 0, 0, 0);
175    
176    gtk_about_dialog_set_comments(about,    GtkWidget *hbox = gtk_hbox_new(FALSE, 8);
177         _("Mobile OSM Editor"));    gtk_box_pack_start(GTK_BOX(hbox),
178                         gtk_label_new(_("Do you ĺike OSM2Go?")),
179                         FALSE, FALSE, 0);
180    
181      GtkWidget *button = gtk_button_new();
182      gtk_button_set_image(GTK_BUTTON(button),
183                           icon_widget_load(&context.appdata->icon, "paypal"));
184      gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
185      g_signal_connect(button, "clicked",
186                       G_CALLBACK(on_paypal_button_clicked), &context);
187      gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
188    
189      gtk_container_add(GTK_CONTAINER(alignment), hbox);
190      gtk_box_pack_start_defaults(GTK_BOX((GTK_DIALOG(context.dialog))->vbox),
191                                  alignment);
192    
193    gtk_widget_show_all(GTK_WIDGET(about));    gtk_widget_show_all(alignment);
194    gtk_dialog_run(GTK_DIALOG(about));  #endif
195    gtk_widget_destroy(GTK_WIDGET(about));  
196      gtk_dialog_run(GTK_DIALOG(context.dialog));
197      gtk_widget_destroy(context.dialog);
198  }  }
199    
200  void on_window_destroy (GtkWidget *widget, gpointer data);  void on_window_destroy (GtkWidget *widget, gpointer data);
201    
202    #ifndef USE_HILDON
203  static void  static void
204  cb_menu_quit(GtkWidget *window, gpointer data) {  cb_menu_quit(GtkMenuItem *item, gpointer data) {
205    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
206    gtk_widget_destroy(GTK_WIDGET(appdata->window));    gtk_widget_destroy(GTK_WIDGET(appdata->window));
207  }  }
208    #endif
209    
210  static void  static void
211  cb_menu_upload(GtkWidget *window, gpointer data) {  cb_menu_upload(GtkMenuItem *item, gpointer data) {
212    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
213    if(!appdata->osm || !appdata->project) return;    if(!appdata->osm || !appdata->project) return;
214    
215      if(project_check_demo(GTK_WIDGET(appdata->window), appdata->project))
216        return;
217    
218    osm_upload(appdata, appdata->osm, appdata->project);    osm_upload(appdata, appdata->osm, appdata->project);
219  }  }
220    
221  static void  static void
222  cb_menu_download(GtkWidget *window, gpointer data) {  cb_menu_download(GtkMenuItem *item, gpointer data) {
223    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
224    if(!appdata->project) return;    if(!appdata->project) return;
225    
226      if(project_check_demo(GTK_WIDGET(appdata->window), appdata->project))
227        return;
228    
229    /* if we have valid osm data loaded: save state first */    /* if we have valid osm data loaded: save state first */
230    if(appdata->osm) {    if(appdata->osm) {
231      /* redraw the entire map by destroying all map items and redrawing them */      /* redraw the entire map by destroying all map items and redrawing them */
232      diff_save(appdata->project, appdata->osm);      diff_save(appdata->project, appdata->osm);
233      map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);      map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
     osm_free(&appdata->icon, appdata->osm);  
234    
235        osm_free(&appdata->icon, appdata->osm);
236      appdata->osm = NULL;      appdata->osm = NULL;
237    }    }
238    
239    // download    // download
240    if(osm_download(GTK_WIDGET(appdata->window), appdata->project)) {    if(osm_download(GTK_WIDGET(appdata->window), appdata->settings,
241      banner_busy_start(appdata, 1, "Redrawing...");                    appdata->project)) {
242      appdata->osm = osm_parse(appdata->project->osm);      banner_busy_start(appdata, 1, "Redrawing");
243        appdata->osm = osm_parse(appdata->project->path, appdata->project->osm);
244      diff_restore(appdata, appdata->project, appdata->osm);      diff_restore(appdata, appdata->project, appdata->osm);
245      map_paint(appdata);      map_paint(appdata);
246      banner_busy_stop(appdata); //"Redrawing..."      banner_busy_stop(appdata); //"Redrawing"
247    }    }
248    
249    main_ui_enable(appdata);    main_ui_enable(appdata);
250  }  }
251    
252  static void  static void
253  cb_menu_wms_import(GtkWidget *window, gpointer data) {  cb_menu_wms_import(GtkMenuItem *item, gpointer data) {
254    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
255    wms_import(appdata);    wms_import(appdata);
256  }  }
257    
258  static void  static void
259  cb_menu_wms_clear(GtkWidget *window, gpointer data) {  cb_menu_wms_clear(GtkMenuItem *item, gpointer data) {
260    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
261    wms_remove(appdata);    wms_remove(appdata);
262  }  }
263    
264  static void  static void
265  cb_menu_wms_adjust(GtkWidget *window, gpointer data) {  cb_menu_wms_adjust(GtkMenuItem *item, gpointer data) {
266    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
267    map_action_set(appdata, MAP_ACTION_BG_ADJUST);    map_action_set(appdata, MAP_ACTION_BG_ADJUST);
268  }  }
# Line 178  cb_menu_wms_adjust(GtkWidget *window, gp Line 270  cb_menu_wms_adjust(GtkWidget *window, gp
270  /* ----------- hide objects for performance reasons ----------- */  /* ----------- hide objects for performance reasons ----------- */
271    
272  static void  static void
273  cb_menu_map_hide_sel(GtkWidget *window, gpointer data) {  cb_menu_map_hide_sel(GtkMenuItem *item, gpointer data) {
274    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
275    map_hide_selected(appdata);    map_hide_selected(appdata);
276  }  }
277    
278  static void  static void
279  cb_menu_map_show_all(GtkWidget *window, gpointer data) {  cb_menu_map_show_all(GtkMenuItem *item, gpointer data) {
280    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
281    map_show_all(appdata);    map_show_all(appdata);
282  }  }
283    
284  /* ---------------------------------------------------------- */  /* ---------------------------------------------------------- */
285    
286  #if 1  // mainly for testing  #if defined(USE_HILDON) && (MAEMO_VERSION_MAJOR == 5)
287  static void  #define MENU_CHECK_ITEM HildonCheckButton
288  cb_menu_redraw(GtkWidget *window, gpointer data) {  #define MENU_CHECK_ITEM_ACTIVE(a) hildon_check_button_get_active(a)
289    appdata_t *appdata = (appdata_t*)data;  #else
290    #define MENU_CHECK_ITEM GtkCheckMenuItem
291    /* redraw the entire map by destroying all map items and redrawing them */  #define MENU_CHECK_ITEM_ACTIVE(a) gtk_check_menu_item_get_active(a)
   banner_busy_start(appdata, 1, "Redrawing...");  
   track_save(appdata->project, appdata->track.track);  
   diff_save(appdata->project, appdata->osm);  
   map_clear(appdata, MAP_LAYER_ALL);  
   osm_free(&appdata->icon, appdata->osm);  
   
   appdata->osm = osm_parse(appdata->project->osm);  
   diff_restore(appdata, appdata->project, appdata->osm);  
   map_paint(appdata);  
   
   appdata->track.track = track_restore(appdata, appdata->project);  
   if(appdata->track.track)  
     map_track_draw(appdata->map, appdata->track.track);  
   
   wms_load(appdata);  
   banner_busy_stop(appdata); //"Redrawing..."  
 }  
292  #endif  #endif
293    
294  static void  static void
295  cb_menu_style(GtkWidget *widget, gpointer data) {  cb_menu_style(GtkMenuItem *item, gpointer data) {
296    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
297    
298    style_select(GTK_WIDGET(appdata->window), appdata);    style_select(GTK_WIDGET(appdata->window), appdata);
299  }  }
300    
301  static void  static void
302  cb_menu_map_no_icons(GtkWidget *widget, gpointer data) {  cb_menu_undo(GtkMenuItem *item, gpointer data) {
   appdata_t *appdata = (appdata_t*)data;  
   
   banner_busy_start(appdata, 1, "Redrawing...");  
   map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);  
   appdata->settings->no_icons =  
     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));  
   map_paint(appdata);  
   banner_busy_stop(appdata); //"Redrawing..."  
 }  
   
 static void  
 cb_menu_map_no_antialias(GtkWidget *widget, gpointer data) {  
   appdata_t *appdata = (appdata_t*)data;  
   
   banner_busy_start(appdata, 1, "Redrawing...");  
   map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);  
   appdata->settings->no_antialias =  
     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));  
   map_paint(appdata);  
   banner_busy_stop(appdata); //"Redrawing..."  
 }  
   
 static void  
 cb_menu_undo(GtkWidget *widget, gpointer data) {  
303    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
304    
305    undo(appdata);    undo(appdata);
# Line 257  cb_menu_undo(GtkWidget *widget, gpointer Line 308  cb_menu_undo(GtkWidget *widget, gpointer
308  }  }
309    
310  static void  static void
311  cb_menu_save_changes(GtkWidget *widget, gpointer data) {  cb_menu_save_changes(GtkMenuItem *item, gpointer data) {
312    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
313    
314    diff_save(appdata->project, appdata->osm);    diff_save(appdata->project, appdata->osm);
# Line 265  cb_menu_save_changes(GtkWidget *widget, Line 316  cb_menu_save_changes(GtkWidget *widget,
316  }  }
317    
318  static void  static void
319  cb_menu_undo_changes(GtkWidget *widget, gpointer data) {  cb_menu_undo_changes(GtkMenuItem *item, gpointer data) {
320    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
321    
322    if(!yes_no_f(GTK_WIDGET(appdata->window), NULL, 0, 0,    if(!yes_no_f(GTK_WIDGET(appdata->window), NULL, 0, 0,
323                 _("Discard local changes?"),                 _("Undo all changes?"),
324                 _("Throw away all the changes you've not "                 _("Throw away all the changes you've not "
325                   "uploaded yet? This can't be undone.")))                   "uploaded yet? This can't be undone.")))
326      return;      return;
327    
328    banner_busy_start(appdata, 1, _("Redrawing..."));    banner_busy_start(appdata, 1, _("Redrawing"));
329    map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);    map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
330    
331    osm_free(&appdata->icon, appdata->osm);    osm_free(&appdata->icon, appdata->osm);
332      appdata->osm = NULL;
333    
334    diff_remove(appdata->project);    diff_remove(appdata->project);
335    appdata->osm = osm_parse(appdata->project->osm);    appdata->osm = osm_parse(appdata->project->path, appdata->project->osm);
336    map_paint(appdata);    map_paint(appdata);
337    banner_busy_stop(appdata);  //"Redrawing..."    banner_busy_stop(appdata);  //"Redrawing"
338    
339    banner_show_info(appdata, _("Discarded local changes"));    banner_show_info(appdata, _("Undo all changes"));
340  }  }
341    
342  static void  static void
343  cb_menu_osm_relations(GtkWidget *widget, gpointer data) {  cb_menu_osm_relations(GtkMenuItem *item, appdata_t *appdata) {
344    relation_list((appdata_t*)data);    /* list relations of all objects */
345      relation_list(GTK_WIDGET(appdata->window), appdata, NULL);
346  }  }
347    
348    #if !defined(USE_HILDON) || (MAEMO_VERSION_MAJOR < 5)
349  static void  static void
350  cb_menu_fullscreen(GtkWidget *widget, gpointer data) {  cb_menu_fullscreen(MENU_CHECK_ITEM *item, gpointer data) {
351    appdata_t *appdata = (appdata_t *)data;    appdata_t *appdata = (appdata_t *)data;
352    
353    if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))    if(MENU_CHECK_ITEM_ACTIVE(item))
354      gtk_window_fullscreen(GTK_WINDOW(appdata->window));      gtk_window_fullscreen(GTK_WINDOW(appdata->window));
355    else    else
356      gtk_window_unfullscreen(GTK_WINDOW(appdata->window));      gtk_window_unfullscreen(GTK_WINDOW(appdata->window));
357  }  }
358    #endif
359    
360  static void  static void
361  cb_menu_zoomin(GtkWidget *widget, appdata_t *appdata) {  cb_menu_zoomin(GtkMenuItem *item, appdata_t *appdata) {
362    if(!appdata || !appdata->map) return;    if(!appdata || !appdata->map) return;
363    
364    map_set_zoom(appdata->map, appdata->map->state->zoom*ZOOM_FACTOR_MENU, TRUE);    map_set_zoom(appdata->map, appdata->map->state->zoom*ZOOM_FACTOR_MENU, TRUE);
# Line 309  cb_menu_zoomin(GtkWidget *widget, appdat Line 366  cb_menu_zoomin(GtkWidget *widget, appdat
366  }  }
367    
368  static void  static void
369  cb_menu_zoomout(GtkWidget *widget, appdata_t *appdata) {  cb_menu_zoomout(GtkMenuItem *item, appdata_t *appdata) {
370    if(!appdata || !appdata->map) return;    if(!appdata || !appdata->map) return;
371    
372    map_set_zoom(appdata->map, appdata->map->state->zoom/ZOOM_FACTOR_MENU, TRUE);    map_set_zoom(appdata->map, appdata->map->state->zoom/ZOOM_FACTOR_MENU, TRUE);
373    printf("zoom is now %f\n", appdata->map->state->zoom);    printf("zoom is now %f\n", appdata->map->state->zoom);
374  }  }
375    
376    #if defined(FREMANTLE) || (MAEMO_VERSION_MAJOR != 5) || !defined(DETAIL_POPUP)
377  static void  static void
378  cb_menu_track_import(GtkWidget *window, appdata_t *appdata) {  cb_menu_view_detail_inc(GtkMenuItem *item, gpointer data) {
379      appdata_t *appdata = (appdata_t*)data;
380    
381      printf("detail level increase\n");
382      map_detail_increase(appdata->map);
383    }
384    
385    static void
386    cb_menu_view_detail_normal(GtkMenuItem *item, gpointer data) {
387      appdata_t *appdata = (appdata_t*)data;
388    
389      printf("detail level normal\n");
390      map_detail_normal(appdata->map);
391    }
392    
393    static void
394    cb_menu_view_detail_dec(GtkMenuItem *item, gpointer data) {
395      appdata_t *appdata = (appdata_t*)data;
396    
397      printf("detail level decrease\n");
398      map_detail_decrease(appdata->map);
399    }
400    #endif
401    
402    static void
403    cb_menu_track_import(GtkMenuItem *item, appdata_t *appdata) {
404      g_assert(appdata->settings);
405    
406    /* open a file selector */    /* open a file selector */
407    GtkWidget *dialog;    GtkWidget *dialog;
# Line 334  cb_menu_track_import(GtkWidget *window, Line 418  cb_menu_track_import(GtkWidget *window,
418                          NULL);                          NULL);
419  #endif  #endif
420    
421    /* use path if one is present */    if(appdata->settings->track_path) {
422    if(appdata->track.import_path)      if(!g_file_test(appdata->settings->track_path, G_FILE_TEST_EXISTS)) {
423      gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),        char *last_sep = strrchr(appdata->settings->track_path, '/');
424                                          appdata->track.import_path);        if(last_sep) {
425            *last_sep = 0;  // seperate path from file
426    
427            /* the user just created a new document */
428            gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
429                                        appdata->settings->track_path);
430            gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
431                                              last_sep+1);
432    
433            /* restore full filename */
434            *last_sep = '/';
435          }
436        } else
437          gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
438                                        appdata->settings->track_path);
439      }
440    
441    gtk_widget_show_all (GTK_WIDGET(dialog));    gtk_widget_show_all (GTK_WIDGET(dialog));
442    if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {    if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {
443      char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));      char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
444    
445      /* load a track */      /* load a track */
446      track_do(appdata, TRACK_IMPORT, filename);      appdata->track.track = track_import(appdata, filename);
447      if(appdata->track.track) {      if(appdata->track.track) {
448          if(appdata->settings->track_path) g_free(appdata->settings->track_path);
449        /* save path if gpx was successfully loaded */        appdata->settings->track_path = g_strdup(filename);
       char *r = strrchr(filename, '/');  
   
       /* there is a delimiter, use everything left of it as path */  
       if(r) {  
         *r = 0;  
         if(appdata->track.import_path) g_free(appdata->track.import_path);  
         appdata->track.import_path = g_strdup(filename);  
         /* restore path ... just in case ... */  
         *r = '/';  
       }  
450      }      }
451      g_free (filename);      g_free (filename);
452    }    }
# Line 366  cb_menu_track_import(GtkWidget *window, Line 455  cb_menu_track_import(GtkWidget *window,
455  }  }
456    
457  static void  static void
458  cb_menu_track_gps(GtkWidget *window, gpointer data) {  cb_menu_track_enable_gps(MENU_CHECK_ITEM *item, appdata_t *appdata) {
459    appdata_t *appdata = (appdata_t*)data;    track_enable_gps(appdata, MENU_CHECK_ITEM_ACTIVE(item));
460    }
461    
462    if(gtk_check_menu_item_get_active(  
463      GTK_CHECK_MENU_ITEM(appdata->track.menu_item_gps))) {  static void
464      track_do(appdata, TRACK_GPS, NULL);  cb_menu_track_follow_gps(MENU_CHECK_ITEM *item, appdata_t *appdata) {
465    } else {    appdata->settings->follow_gps = MENU_CHECK_ITEM_ACTIVE(item);
     track_do(appdata, TRACK_NONE, NULL);  
   }  
466  }  }
467    
468    
469  static void  static void
470  cb_menu_track_export(GtkWidget *window, gpointer data) {  cb_menu_track_export(GtkMenuItem *item, appdata_t *appdata) {
471    appdata_t *appdata = (appdata_t*)data;    g_assert(appdata->settings);
472    messagef(GTK_WIDGET(appdata->window), _("NIY"),  
473             _("Track export is not yet supported."));    /* open a file selector */
474      GtkWidget *dialog;
475    
476    #ifdef USE_HILDON
477      dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(appdata->window),
478                                              GTK_FILE_CHOOSER_ACTION_SAVE);
479    #else
480      dialog = gtk_file_chooser_dialog_new(_("Export track file"),
481                                           GTK_WINDOW(appdata->window),
482                                           GTK_FILE_CHOOSER_ACTION_SAVE,
483                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
484                                           GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
485                                           NULL);
486    #endif
487    
488      printf("set filename <%s>\n", appdata->settings->track_path);
489    
490      if(appdata->settings->track_path) {
491        if(!g_file_test(appdata->settings->track_path, G_FILE_TEST_EXISTS)) {
492          char *last_sep = strrchr(appdata->settings->track_path, '/');
493          if(last_sep) {
494            *last_sep = 0;  // seperate path from file
495    
496            /* the user just created a new document */
497            gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
498                                                appdata->settings->track_path);
499            gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
500                                              last_sep+1);
501    
502            /* restore full filename */
503            *last_sep = '/';
504          }
505        } else
506          gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
507                                        appdata->settings->track_path);
508      }
509    
510      if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_FM_OK) {
511        gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
512        if(filename) {
513          printf("export to %s\n", filename);
514    
515          if(!g_file_test(filename, G_FILE_TEST_EXISTS) ||
516             yes_no_f(dialog, appdata, MISC_AGAIN_ID_EXPORT_OVERWRITE,
517                      MISC_AGAIN_FLAG_DONT_SAVE_NO,
518                      "Overwrite existing file",
519                      "The file already exists. "
520                      "Do you really want to replace it?")) {
521            if(appdata->settings->track_path)
522              g_free(appdata->settings->track_path);
523            appdata->settings->track_path = g_strdup(filename);
524    
525            track_export(appdata, filename);
526          }
527        }
528      }
529    
530      gtk_widget_destroy (dialog);
531  }  }
532    
533    
534  static void  static void
535  cb_menu_track_clear(GtkWidget *window, gpointer data) {  cb_menu_track_clear(GtkMenuItem *item, gpointer data) {
536    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
537    track_do(appdata, TRACK_NONE, NULL);    track_clear(appdata, appdata->track.track);
538      appdata->track.track = NULL;
539  }  }
540    
541    
# Line 421  cb_menu_track_clear(GtkWidget *window, g Line 569  cb_menu_track_clear(GtkWidget *window, g
569  #endif  #endif
570    
571    
572    #if !defined(USE_HILDON) || (MAEMO_VERSION_MAJOR < 5)
573  // Half-arsed slapdash common menu item constructor. Let's use GtkBuilder  // Half-arsed slapdash common menu item constructor. Let's use GtkBuilder
574  // instead so we have some flexibility.  // instead so we have some flexibility.
575    
# Line 435  menu_append_new_item(appdata_t *appdata, Line 583  menu_append_new_item(appdata_t *appdata,
583                       const gchar *accel_path,                       const gchar *accel_path,
584                       guint accel_key,      // from gdk/gdkkeysyms.h                       guint accel_key,      // from gdk/gdkkeysyms.h
585                       GdkModifierType accel_mods, // e.g. GDK_CONTROL_MASK                       GdkModifierType accel_mods, // e.g. GDK_CONTROL_MASK
586                         gboolean enabled,
587                       gboolean is_check, gboolean check_status)                       gboolean is_check, gboolean check_status)
588  {  {
589    GtkWidget *item = NULL;    GtkWidget *item = NULL;
# Line 490  menu_append_new_item(appdata_t *appdata, Line 639  menu_append_new_item(appdata_t *appdata,
639  #endif  #endif
640    
641    gtk_menu_shell_append(GTK_MENU_SHELL(menu_shell), GTK_WIDGET(item));    gtk_menu_shell_append(GTK_MENU_SHELL(menu_shell), GTK_WIDGET(item));
642    if (is_check) {    gtk_widget_set_sensitive(GTK_WIDGET(item), enabled);
643      if (is_check)
644      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), check_status);      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), check_status);
645    }  
646    g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(activate_cb),    g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(activate_cb),
647                     appdata);                     appdata);
648    return item;    return item;
649  }  }
650    
   
651  void menu_create(appdata_t *appdata) {  void menu_create(appdata_t *appdata) {
652    GtkWidget *menu, *item, *submenu;    GtkWidget *menu, *item, *submenu;
653    GtkWidget *about_quit_items_menu;    GtkWidget *about_quit_items_menu;
# Line 513  void menu_create(appdata_t *appdata) { Line 662  void menu_create(appdata_t *appdata) {
662    /* -------------------- Project submenu -------------------- */    /* -------------------- Project submenu -------------------- */
663    
664    GtkAccelGroup *accel_grp = gtk_accel_group_new();    GtkAccelGroup *accel_grp = gtk_accel_group_new();
665    
666    #ifndef USE_HILDON
667    item = gtk_menu_item_new_with_mnemonic( _("_Project") );    item = gtk_menu_item_new_with_mnemonic( _("_Project") );
668    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
669    submenu = gtk_menu_new();    submenu = gtk_menu_new();
# Line 523  void menu_create(appdata_t *appdata) { Line 674  void menu_create(appdata_t *appdata) {
674  #endif  #endif
675    
676    menu_append_new_item(    menu_append_new_item(
677      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_project_open), _("_Open..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_project_open), _("_Open"),
678      GTK_STOCK_OPEN, "<OSM2Go-Main>/Project/Open",      GTK_STOCK_OPEN, "<OSM2Go-Main>/Project/Open",
679      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
680    );    );
681    
682    appdata->menu_item_project_close = menu_append_new_item(    menu_append_new_item(
683      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_project_close), _("_Close"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_project_wizard), _("_Wizard"),
684      GTK_STOCK_CLOSE, "<OSM2Go-Main>/Project/Close",      GTK_STOCK_NEW, "<OSM2Go-Main>/Project/Wizard",
685      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
686      );
687    #else
688      menu_append_new_item(
689        appdata, menu, GTK_SIGNAL_FUNC(cb_menu_project_open), _("_Project"),
690        GTK_STOCK_OPEN, "<OSM2Go-Main>/Project",
691        0, 0, TRUE, FALSE, FALSE
692    );    );
693    #endif
694    
695    /* --------------- view menu ------------------- */    /* --------------- view menu ------------------- */
696    
# Line 540  void menu_create(appdata_t *appdata) { Line 698  void menu_create(appdata_t *appdata) {
698    gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());    gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
699  #endif  #endif
700    
701    appdata->menu_view = item = gtk_menu_item_new_with_mnemonic( _("_View") );    appdata->submenu_view = item = gtk_menu_item_new_with_mnemonic( _("_View") );
702    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
703    submenu = gtk_menu_new();    submenu = gtk_menu_new();
704    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
705    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
706    
707    #if !defined(USE_HILDON) || (MAEMO_VERSION_MAJOR < 5)
708    appdata->menu_item_view_fullscreen = menu_append_new_item(    appdata->menu_item_view_fullscreen = menu_append_new_item(
709      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_fullscreen), _("_Fullscreen"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_fullscreen), _("_Fullscreen"),
710      GTK_STOCK_FULLSCREEN, "<OSM2Go-Main>/View/Fullscreen",      GTK_STOCK_FULLSCREEN, "<OSM2Go-Main>/View/Fullscreen",
711      0, 0, TRUE, FALSE      0, 0, TRUE, TRUE, FALSE
712    );    );
713    #endif
714    
715    #if !defined(ZOOM_BUTTONS) || !defined(USE_HILDON)
716    menu_append_new_item(    menu_append_new_item(
717      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_zoomin), _("Zoom _in"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_zoomin), _("Zoom _in"),
718      GTK_STOCK_ZOOM_IN, "<OSM2Go-Main>/View/ZoomIn",      GTK_STOCK_ZOOM_IN, "<OSM2Go-Main>/View/ZoomIn",
719      GDK_comma, GDK_CONTROL_MASK, FALSE, FALSE      GDK_comma, GDK_CONTROL_MASK, TRUE, FALSE, FALSE
720    );    );
721    
722    menu_append_new_item(    menu_append_new_item(
723      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_zoomout), _("Zoom _out"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_zoomout), _("Zoom _out"),
724      GTK_STOCK_ZOOM_OUT, "<OSM2Go-Main>/View/ZoomOut",      GTK_STOCK_ZOOM_OUT, "<OSM2Go-Main>/View/ZoomOut",
725      GDK_period, GDK_CONTROL_MASK, FALSE, FALSE      GDK_period, GDK_CONTROL_MASK, TRUE, FALSE, FALSE
726      );
727    #endif
728    
729      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
730    
731      menu_append_new_item(
732        appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_view_detail_inc), _("More details"),
733        NULL, "<OSM2Go-Main>/View/DetailInc",
734        GDK_period, GDK_MOD1_MASK, TRUE, FALSE, FALSE
735      );
736    
737      menu_append_new_item(
738        appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_view_detail_normal), _("Normal details"),
739        NULL, "<OSM2Go-Main>/View/DetailNormal",
740        0, 0, TRUE, FALSE, FALSE
741      );
742    
743      menu_append_new_item(
744        appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_view_detail_dec), _("Less details"),
745        NULL, "<OSM2Go-Main>/View/DetailDec",
746        GDK_comma, GDK_MOD1_MASK, TRUE, FALSE, FALSE
747      );
748    
749      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
750    
751      appdata->menu_item_map_hide_sel = menu_append_new_item(
752        appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_hide_sel), _("_Hide selected"),
753        GTK_STOCK_REMOVE, "<OSM2Go-Main>/View/HideSelected",
754        0, 0, TRUE, FALSE, FALSE
755      );
756      gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, FALSE);
757    
758      appdata->menu_item_map_show_all = menu_append_new_item(
759        appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_show_all), _("_Show all"),
760        GTK_STOCK_ADD, "<OSM2Go-Main>/View/ShowAll",
761        0, 0, TRUE, FALSE, FALSE
762      );
763      gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);
764    
765      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
766    
767      menu_append_new_item(
768        appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_style), _("St_yle"),
769        GTK_STOCK_SELECT_COLOR, "<OSM2Go-Main>/View/Style",
770        0, 0, TRUE, FALSE, FALSE
771    );    );
772    
773    /* -------------------- OSM submenu -------------------- */    /* -------------------- map submenu -------------------- */
774    
775    appdata->menu_osm = item = gtk_menu_item_new_with_mnemonic( _("_OSM") );    appdata->submenu_map = item = gtk_menu_item_new_with_mnemonic( _("_Map") );
776    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
777    submenu = gtk_menu_new();    submenu = gtk_menu_new();
778    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
779    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
780    
781    appdata->menu_item_osm_upload = menu_append_new_item(    appdata->menu_item_map_upload = menu_append_new_item(
782      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_upload), _("_Upload..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_upload), _("_Upload"),
783      "upload.16", "<OSM2Go-Main>/OSM/Upload",      "upload.16", "<OSM2Go-Main>/Map/Upload",
784      GDK_u, GDK_SHIFT_MASK|GDK_CONTROL_MASK, FALSE, FALSE      GDK_u, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
785    );    );
786    
787    menu_append_new_item(    menu_append_new_item(
788      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_download), _("_Download..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_download), _("_Download"),
789      "download.16", "<OSM2Go-Main>/OSM/Download",      "download.16", "<OSM2Go-Main>/Map/Download",
790      GDK_d, GDK_SHIFT_MASK|GDK_CONTROL_MASK, FALSE, FALSE      GDK_d, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
791    );    );
792    
793    gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());    gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
794    
795    if(getenv("OSM2GO_UNDO_TEST")) {    if(getenv("OSM2GO_UNDO_TEST")) {
796      appdata->menu_item_osm_undo = menu_append_new_item(      appdata->menu_item_map_undo = menu_append_new_item(
797                 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_undo), _("_Undo"),                 appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_undo), _("_Undo"),
798                 GTK_STOCK_UNDO, "<OSM2Go-Main>/OSM/Undo",                 GTK_STOCK_UNDO, "<OSM2Go-Main>/Map/Undo",
799                 GDK_z, GDK_CONTROL_MASK, FALSE, FALSE                 GDK_z, GDK_CONTROL_MASK, TRUE, FALSE, FALSE
800                 );                 );
801    } else    } else
802      printf("set environment variable OSM2GO_UNDO_TEST to enable undo framework tests\n");      printf("set environment variable OSM2GO_UNDO_TEST to enable undo framework tests\n");
803    
804    appdata->menu_item_osm_save_changes = menu_append_new_item(  #ifndef USE_HILDON
805      appdata->menu_item_map_save_changes = menu_append_new_item(
806      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_save_changes), _("_Save local changes"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_save_changes), _("_Save local changes"),
807      GTK_STOCK_SAVE, "<OSM2Go-Main>/OSM/SaveChanges",      GTK_STOCK_SAVE, "<OSM2Go-Main>/Map/SaveChanges",
808      GDK_s, GDK_SHIFT_MASK|GDK_CONTROL_MASK, FALSE, FALSE      GDK_s, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
809    );    );
810    #endif
811    
812    appdata->menu_item_osm_undo_changes = menu_append_new_item(    appdata->menu_item_map_undo_changes = menu_append_new_item(
813      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_undo_changes), _("Disca_rd local changes..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_undo_changes), _("Undo _all"),
814      GTK_STOCK_DELETE, "<OSM2Go-Main>/OSM/DiscardChanges",      GTK_STOCK_DELETE, "<OSM2Go-Main>/Map/UndoAll",
815      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
816    );    );
817    
818    gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());    gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
819    appdata->menu_item_osm_relations = menu_append_new_item(    appdata->menu_item_map_relations = menu_append_new_item(
820      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_osm_relations), _("_Relations..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_osm_relations), _("_Relations"),
821      NULL, "<OSM2Go-Main>/OSM/Relations",      NULL, "<OSM2Go-Main>/Map/Relations",
822      GDK_r, GDK_SHIFT_MASK|GDK_CONTROL_MASK, FALSE, FALSE      GDK_r, GDK_SHIFT_MASK|GDK_CONTROL_MASK, TRUE, FALSE, FALSE
823    );    );
824    
825    /* -------------------- wms submenu -------------------- */    /* -------------------- wms submenu -------------------- */
826    
827    appdata->menu_wms = item = gtk_menu_item_new_with_mnemonic( _("_WMS") );    appdata->submenu_wms = item = gtk_menu_item_new_with_mnemonic( _("_WMS") );
828    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
829    submenu = gtk_menu_new();    submenu = gtk_menu_new();
830    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
831    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
832    
833    menu_append_new_item(    menu_append_new_item(
834      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_import), _("_Import..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_import), _("_Import"),
835      GTK_STOCK_INDEX, "<OSM2Go-Main>/WMS/Import",      GTK_STOCK_INDEX, "<OSM2Go-Main>/WMS/Import",
836      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
837    );    );
838    
839    appdata->menu_item_wms_clear = menu_append_new_item(    appdata->menu_item_wms_clear = menu_append_new_item(
840      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_clear), _("_Clear"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_clear), _("_Clear"),
841      GTK_STOCK_CLEAR, "<OSM2Go-Main>/WMS/Clear",      GTK_STOCK_CLEAR, "<OSM2Go-Main>/WMS/Clear",
842      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
843    );    );
844    gtk_widget_set_sensitive(appdata->menu_item_wms_clear, FALSE);    gtk_widget_set_sensitive(appdata->menu_item_wms_clear, FALSE);
845    
846    appdata->menu_item_wms_adjust = menu_append_new_item(    appdata->menu_item_wms_adjust = menu_append_new_item(
847      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_adjust), _("_Adjust"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_wms_adjust), _("_Adjust"),
848      NULL, "<OSM2Go-Main>/WMS/Adjust",      NULL, "<OSM2Go-Main>/WMS/Adjust",
849      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
850    );    );
851    gtk_widget_set_sensitive(appdata->menu_item_wms_adjust, FALSE);    gtk_widget_set_sensitive(appdata->menu_item_wms_adjust, FALSE);
852    
   /* -------------------- map submenu -------------------- */  
   
   appdata->menu_map = item = gtk_menu_item_new_with_mnemonic( _("_Map") );  
   gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);  
   submenu = gtk_menu_new();  
   gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);  
   gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);  
   
   appdata->menu_item_map_hide_sel = menu_append_new_item(  
     appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_hide_sel), _("_Hide selected"),  
     GTK_STOCK_REMOVE, "<OSM2Go-Main>/Map/HideSelected",  
     0, 0, FALSE, FALSE  
   );  
   gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, FALSE);  
   
   appdata->menu_item_map_show_all = menu_append_new_item(  
     appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_show_all), _("_Show all"),  
     GTK_STOCK_ADD, "<OSM2Go-Main>/Map/ShowAll",  
     0, 0, FALSE, FALSE  
   );  
   gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);  
   
   gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());  
   
   menu_append_new_item(  
     appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_style), _("St_yle..."),  
     GTK_STOCK_SELECT_COLOR, "<OSM2Go-Main>/Map/Style",  
     0, 0, FALSE, FALSE  
   );  
   
   gtk_menu_shell_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());  
   
   /* switches mainly intended for testing/debugging */  
   menu_append_new_item(  
     appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_redraw), _("_Redraw"),  
     NULL, "<OSM2Go-Main>/Map/Redraw",  
     GDK_r, GDK_CONTROL_MASK, FALSE, FALSE  
   );  
   
   appdata->menu_item_map_no_icons = menu_append_new_item(  
     appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_no_icons), _("No _icons"),  
     NULL, "<OSM2Go-Main>/Map/NoIcons",  
     0, 0, TRUE, appdata->settings->no_icons  
   );  
   
   appdata->menu_item_map_no_antialias = menu_append_new_item(  
     appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_map_no_antialias),  
     _("No _antialias"),  
     NULL, "<OSM2Go-Main>/Map/NoAntialias",  
     0, 0, TRUE, appdata->settings->no_antialias  
   );  
   
853    /* -------------------- track submenu -------------------- */    /* -------------------- track submenu -------------------- */
854    
855    appdata->track.menu_track = item = gtk_menu_item_new_with_mnemonic(_("_Track"));    appdata->track.submenu_track = item =
856        gtk_menu_item_new_with_mnemonic(_("_Track"));
857    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
858    submenu = gtk_menu_new();    submenu = gtk_menu_new();
859    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);    gtk_menu_set_accel_group(GTK_MENU(submenu), accel_grp);
860    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
861    
862    appdata->track.menu_item_import = menu_append_new_item(    appdata->track.menu_item_track_import = menu_append_new_item(
863      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_import), _("_Import..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_import), _("_Import"),
864      NULL, "<OSM2Go-Main>/Track/Import",      NULL, "<OSM2Go-Main>/Track/Import",
865      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
866    );    );
867    
868    appdata->track.menu_item_export = menu_append_new_item(    appdata->track.menu_item_track_export = menu_append_new_item(
869      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_export), _("_Export..."),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_export), _("_Export"),
870      NULL, "<OSM2Go-Main>/Track/Export",      NULL, "<OSM2Go-Main>/Track/Export",
871      0, 0, FALSE, FALSE      0, 0, FALSE, FALSE, FALSE
872    );    );
873    
874    appdata->track.menu_item_clear = menu_append_new_item(    appdata->track.menu_item_track_clear = menu_append_new_item(
875      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_clear), _("_Clear"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_clear), _("_Clear"),
876      GTK_STOCK_CLEAR, "<OSM2Go-Main>/Track/Clear",      GTK_STOCK_CLEAR, "<OSM2Go-Main>/Track/Clear",
877      0, 0, FALSE, FALSE      0, 0, FALSE, FALSE, FALSE
878    );    );
879    
880    
881    appdata->track.menu_item_gps = menu_append_new_item(    appdata->track.menu_item_track_enable_gps = menu_append_new_item(
882      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_gps), _("_GPS"),      appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_enable_gps),_("_GPS enable"),
883      NULL, "<OSM2Go-Main>/Track/GPS",      NULL, "<OSM2Go-Main>/Track/GPS",
884      GDK_g, GDK_CONTROL_MASK|GDK_SHIFT_MASK, TRUE, FALSE      GDK_g, GDK_CONTROL_MASK|GDK_SHIFT_MASK, TRUE, TRUE,
885        appdata->settings->enable_gps
886      );
887    
888      appdata->track.menu_item_track_follow_gps = menu_append_new_item(
889        appdata, submenu, GTK_SIGNAL_FUNC(cb_menu_track_follow_gps), _("GPS follow"),
890        NULL, "<OSM2Go-Main>/Track/Follow",
891        0, 0, appdata->settings->enable_gps, TRUE,
892        appdata->settings->follow_gps
893    );    );
894    
895    /* ------------------------------------------------------- */    /* ------------------------------------------------------- */
# Line 733  void menu_create(appdata_t *appdata) { Line 898  void menu_create(appdata_t *appdata) {
898                          gtk_separator_menu_item_new());                          gtk_separator_menu_item_new());
899    
900    menu_append_new_item(    menu_append_new_item(
901      appdata, about_quit_items_menu, GTK_SIGNAL_FUNC(cb_menu_about), _("_About..."),      appdata, about_quit_items_menu, GTK_SIGNAL_FUNC(cb_menu_about), _("_About"),
902      GTK_STOCK_ABOUT, "<OSM2Go-Main>/About",      GTK_STOCK_ABOUT, "<OSM2Go-Main>/About",
903      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
904    );    );
905    
906    #ifndef USE_HILDON
907    menu_append_new_item(    menu_append_new_item(
908      appdata, about_quit_items_menu, GTK_SIGNAL_FUNC(cb_menu_quit), _("_Quit"),      appdata, about_quit_items_menu, GTK_SIGNAL_FUNC(cb_menu_quit), _("_Quit"),
909      GTK_STOCK_QUIT, "<OSM2Go-Main>/Quit",      GTK_STOCK_QUIT, "<OSM2Go-Main>/Quit",
910      0, 0, FALSE, FALSE      0, 0, TRUE, FALSE, FALSE
911    );    );
912    #endif
913    
914    gtk_window_add_accel_group(GTK_WINDOW(appdata->window), accel_grp);    gtk_window_add_accel_group(GTK_WINDOW(appdata->window), accel_grp);
915    
# Line 769  void menu_create(appdata_t *appdata) { Line 936  void menu_create(appdata_t *appdata) {
936  #endif //USE_HILDON  #endif //USE_HILDON
937  }  }
938    
939    void menu_cleanup(appdata_t *appdata) { }
940    
941    #else // !defined(USE_HILDON) || (MAEMO_VERSION_MAJOR < 5)
942    
943    void submenu_entry(appdata_t *appdata, HildonAppMenu *menu,
944                       const char *label, const char *value,
945                       GtkSignalFunc activate_cb) {
946    
947    }
948    
949    typedef struct {
950      const char *label, *value;
951      gboolean enabled;
952      gboolean (*toggle)(appdata_t *appdata);
953      gulong offset;
954      GtkSignalFunc activate_cb;
955    } menu_entry_t;
956    
957    typedef struct {
958      const char *title;
959      const menu_entry_t *menu;
960      int len;
961    } submenu_t;
962    
963    static gboolean enable_gps_get_toggle(appdata_t *appdata) {
964      if(!appdata)           return FALSE;
965      if(!appdata->settings) return FALSE;
966      return appdata->settings->enable_gps;
967    }
968    
969    static gboolean follow_gps_get_toggle(appdata_t *appdata) {
970      if(!appdata)           return FALSE;
971      if(!appdata->settings) return FALSE;
972      return appdata->settings->follow_gps;
973    }
974    
975    /* create a HildonAppMenu */
976    static GtkWidget *app_menu_create(appdata_t *appdata,
977                                      const menu_entry_t *menu_entries) {
978      HildonAppMenu *menu = HILDON_APP_MENU(hildon_app_menu_new());
979    
980      while(menu_entries->label) {
981        GtkWidget *button = NULL;
982    
983        if(!menu_entries->toggle) {
984          button = hildon_button_new_with_text(
985                HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
986                HILDON_BUTTON_ARRANGEMENT_VERTICAL,
987                _(menu_entries->label), _(menu_entries->value));
988          g_signal_connect_after(button, "clicked",
989                                 menu_entries->activate_cb, appdata);
990        } else {
991          button = hildon_check_button_new(HILDON_SIZE_AUTO);
992          gtk_button_set_label(GTK_BUTTON(button), _(menu_entries->label));
993          printf("requesting check for %s: %p\n", menu_entries->label,
994                 menu_entries->toggle);
995          hildon_check_button_set_active(HILDON_CHECK_BUTTON(button),
996                                         menu_entries->toggle(appdata));
997          g_signal_connect_after(button, "toggled",
998                                 menu_entries->activate_cb, appdata);
999        }
1000    
1001        hildon_button_set_title_alignment(HILDON_BUTTON(button), 0.5, 0.5);
1002        hildon_button_set_value_alignment(HILDON_BUTTON(button), 0.5, 0.5);
1003    
1004        /* offset to GtkWidget pointer was given -> store pointer */
1005        if(menu_entries->offset)
1006          *(GtkWidget**)(((void*)appdata)+menu_entries->offset) = button;
1007    
1008        gtk_widget_set_sensitive(button, menu_entries->enabled);
1009    
1010        hildon_app_menu_append(menu, GTK_BUTTON(button));
1011        menu_entries++;
1012      }
1013    
1014      gtk_widget_show_all(GTK_WIDGET(menu));
1015      return GTK_WIDGET(menu);
1016    }
1017    
1018    #ifdef MAEMO5_SUBMENU_POPUP
1019    static GtkWidget *app_submenu_create(appdata_t *appdata,
1020                                         const submenu_t *submenu) {
1021      return app_menu_create(appdata, submenu->menu);
1022    }
1023    
1024    static void submenu_popup(GtkWidget *menu) {
1025      GtkWidget *top = hildon_window_stack_peek(hildon_window_stack_get_default());
1026    
1027    #if 0 // nasty workaround for race condition in hildonappmenu
1028      int start, end;
1029      GTimeVal tv;
1030      g_get_current_time(&tv);
1031      start = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1032      do {
1033        if(gtk_events_pending())
1034          while(gtk_events_pending()) {
1035            putchar('.'); fflush(stdout);
1036            gtk_main_iteration();
1037          }
1038        else
1039          usleep(100);
1040    
1041        g_get_current_time(&tv);
1042        end = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1043      } while(end-start < 500);
1044    #endif
1045    
1046      hildon_app_menu_popup(HILDON_APP_MENU(menu), GTK_WINDOW(top));
1047    }
1048    
1049    static void submenu_cleanup(GtkWidget *menu) {
1050      g_object_unref(menu);
1051    }
1052    #else
1053    #define COLUMNS  2
1054    
1055    void on_submenu_entry_clicked(GtkButton *button, GtkWidget *menu) {
1056    
1057      /* force closing of submenu dialog */
1058      gtk_dialog_response(GTK_DIALOG(menu), GTK_RESPONSE_NONE);
1059      gtk_widget_hide(menu);
1060    
1061      /* let gtk clean up */
1062      while(gtk_events_pending())
1063        gtk_main_iteration();
1064    }
1065    
1066    /* use standard dialog boxes for fremantle submenues */
1067    static GtkWidget *app_submenu_create(appdata_t *appdata,
1068                                         const submenu_t *submenu) {
1069    
1070      /* create a oridinary dialog box */
1071      GtkWidget *dialog = misc_dialog_new(MISC_DIALOG_SMALL, _(submenu->title),
1072                                          GTK_WINDOW(appdata->window), NULL);
1073    
1074      gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
1075    
1076      GtkWidget *table = gtk_table_new(submenu->len/COLUMNS, COLUMNS, TRUE);
1077      int x = 0, y = 0;
1078    
1079      const menu_entry_t *menu_entries = submenu->menu;
1080      while(menu_entries->label) {
1081        GtkWidget *button = NULL;
1082    
1083        if(!menu_entries->toggle) {
1084          button = hildon_button_new_with_text(
1085                HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1086                HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1087                _(menu_entries->label), _(menu_entries->value));
1088    
1089          g_signal_connect(button, "clicked",
1090                           G_CALLBACK(on_submenu_entry_clicked), dialog);
1091    
1092          g_signal_connect(button, "clicked",
1093                           menu_entries->activate_cb, appdata);
1094    
1095          hildon_button_set_title_alignment(HILDON_BUTTON(button), 0.5, 0.5);
1096          hildon_button_set_value_alignment(HILDON_BUTTON(button), 0.5, 0.5);
1097        } else {
1098          button = hildon_check_button_new(HILDON_SIZE_AUTO);
1099          gtk_button_set_label(GTK_BUTTON(button), _(menu_entries->label));
1100          printf("requesting check for %s: %p\n", menu_entries->label,
1101                 menu_entries->toggle);
1102          hildon_check_button_set_active(HILDON_CHECK_BUTTON(button),
1103                                         menu_entries->toggle(appdata));
1104    
1105          g_signal_connect(button, "clicked",
1106                           G_CALLBACK(on_submenu_entry_clicked), dialog);
1107    
1108          g_signal_connect(button, "toggled",
1109                           menu_entries->activate_cb, appdata);
1110    
1111          gtk_button_set_alignment(GTK_BUTTON(button), 0.5, 0.5);
1112        }
1113    
1114        /* offset to GtkWidget pointer was given -> store pointer */
1115        if(menu_entries->offset)
1116          *(GtkWidget**)(((void*)appdata)+menu_entries->offset) = button;
1117    
1118        gtk_widget_set_sensitive(button, menu_entries->enabled);
1119    
1120        gtk_table_attach_defaults(GTK_TABLE(table),  button, x, x+1, y, y+1);
1121    
1122        x++;
1123        if(x == COLUMNS) { x = 0; y++; }
1124    
1125        menu_entries++;
1126      }
1127    
1128    
1129      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), table);
1130    
1131      return dialog;
1132    }
1133    
1134    /* popup the dialog shaped submenu */
1135    static void submenu_popup(GtkWidget *menu) {
1136      gtk_widget_show_all(menu);
1137      gtk_dialog_run(GTK_DIALOG(menu));
1138      gtk_widget_hide(menu);
1139    }
1140    
1141    static void submenu_cleanup(GtkWidget *menu) {
1142      gtk_widget_destroy(menu);
1143    }
1144    #endif
1145    
1146    /* the view submenu */
1147    void on_submenu_view_clicked(GtkButton *button, appdata_t *appdata) {
1148      submenu_popup(appdata->app_menu_view);
1149    }
1150    
1151    void on_submenu_map_clicked(GtkButton *button, appdata_t *appdata) {
1152      submenu_popup(appdata->app_menu_map);
1153    }
1154    
1155    void on_submenu_wms_clicked(GtkButton *button, appdata_t *appdata) {
1156      submenu_popup(appdata->app_menu_wms);
1157    }
1158    
1159    void on_submenu_track_clicked(GtkButton *button, appdata_t *appdata) {
1160      submenu_popup(appdata->app_menu_track);
1161    }
1162    
1163    #define APP_OFFSET(a)  offsetof(appdata_t, a)
1164    #define SIMPLE_ENTRY(a,b)     { a, NULL, TRUE,   NULL, 0, G_CALLBACK(b) }
1165    #define ENABLED_ENTRY(a,b,c)  { a, NULL, TRUE,  NULL, APP_OFFSET(c), G_CALLBACK(b) }
1166    #define DISABLED_ENTRY(a,b,c) { a, NULL, FALSE,  NULL, APP_OFFSET(c), G_CALLBACK(b) }
1167    #define TOGGLE_ENTRY(a,b,c)   { a, NULL, TRUE, c, 0, G_CALLBACK(b) }
1168    #define DISABLED_TOGGLE_ENTRY(a,b,c,d)  \
1169                                  { a, NULL, FALSE, c, APP_OFFSET(d), G_CALLBACK(b) }
1170    #define ENABLED_TOGGLE_ENTRY(a,b,c,d) \
1171                                  { a, NULL, TRUE, c, APP_OFFSET(d), G_CALLBACK(b) }
1172    #define LAST_ENTRY            { NULL, NULL, FALSE, NULL, 0, NULL }
1173    
1174    /* -- the view submenu -- */
1175    static const menu_entry_t submenu_view_entries[] = {
1176    #ifndef ZOOM_BUTTONS
1177      SIMPLE_ENTRY("Zoom in",         cb_menu_zoomin),
1178      SIMPLE_ENTRY("Zoom out",        cb_menu_zoomout),
1179    #endif
1180      /* --- */
1181      SIMPLE_ENTRY("Style",           cb_menu_style),
1182      /* --- */
1183    #ifndef DETAIL_POPUP
1184      SIMPLE_ENTRY("Normal details",  cb_menu_view_detail_normal),
1185      SIMPLE_ENTRY("More details",    cb_menu_view_detail_inc),
1186      SIMPLE_ENTRY("Less details",    cb_menu_view_detail_dec),
1187    #endif
1188      /* --- */
1189      DISABLED_ENTRY("Hide selected", cb_menu_map_hide_sel, menu_item_map_hide_sel),
1190      DISABLED_ENTRY("Show all",      cb_menu_map_show_all, menu_item_map_show_all),
1191    
1192      LAST_ENTRY
1193    };
1194    
1195    static const submenu_t submenu_view = {
1196      "View", submenu_view_entries,
1197      sizeof(submenu_view_entries)/sizeof(menu_entry_t)-1
1198    };
1199    
1200    /* -- the map submenu -- */
1201    static const menu_entry_t submenu_map_entries[] = {
1202      ENABLED_ENTRY("Upload",                cb_menu_upload, menu_item_map_upload),
1203      SIMPLE_ENTRY("Download",               cb_menu_download),
1204      ENABLED_ENTRY("Undo all",              cb_menu_undo_changes,
1205                    menu_item_map_undo_changes),
1206      ENABLED_ENTRY("Relations",             cb_menu_osm_relations,
1207                    menu_item_map_relations),
1208    
1209      LAST_ENTRY
1210    };
1211    
1212    static const submenu_t submenu_map = {
1213      "Map", submenu_map_entries,
1214      sizeof(submenu_map_entries)/sizeof(menu_entry_t)-1
1215    };
1216    
1217    /* -- the wms submenu -- */
1218    static const menu_entry_t submenu_wms_entries[] = {
1219      SIMPLE_ENTRY("Import",   cb_menu_wms_import),
1220      DISABLED_ENTRY("Clear",  cb_menu_wms_clear, menu_item_wms_clear),
1221      DISABLED_ENTRY("Adjust", cb_menu_wms_adjust, menu_item_wms_adjust),
1222    
1223      LAST_ENTRY
1224    };
1225    
1226    static const submenu_t submenu_wms = {
1227      "WMS", submenu_wms_entries,
1228      sizeof(submenu_wms_entries)/sizeof(menu_entry_t)-1
1229    };
1230    
1231    /* -- the track submenu -- */
1232    static const menu_entry_t submenu_track_entries[] = {
1233      ENABLED_ENTRY("Import",  cb_menu_track_import, track.menu_item_track_import),
1234      DISABLED_ENTRY("Export", cb_menu_track_export, track.menu_item_track_export),
1235      DISABLED_ENTRY("Clear",  cb_menu_track_clear, track.menu_item_track_clear),
1236      ENABLED_TOGGLE_ENTRY("GPS enable", cb_menu_track_enable_gps,
1237                    enable_gps_get_toggle, track.menu_item_track_enable_gps),
1238      DISABLED_TOGGLE_ENTRY("GPS follow", cb_menu_track_follow_gps,
1239                    follow_gps_get_toggle, track.menu_item_track_follow_gps),
1240    
1241      LAST_ENTRY
1242    };
1243    
1244    static const submenu_t submenu_track = {
1245      "Track", submenu_track_entries,
1246      sizeof(submenu_track_entries)/sizeof(menu_entry_t)-1
1247    };
1248    
1249    
1250    /* -- the applications main menu -- */
1251    static const menu_entry_t main_menu[] = {
1252      SIMPLE_ENTRY("About",   cb_menu_about),
1253      SIMPLE_ENTRY("Project", cb_menu_project_open),
1254      ENABLED_ENTRY("View",   on_submenu_view_clicked,  submenu_view),
1255      ENABLED_ENTRY("Map",    on_submenu_map_clicked,   submenu_map),
1256      ENABLED_ENTRY("WMS",    on_submenu_wms_clicked,   submenu_wms),
1257      ENABLED_ENTRY("Track",  on_submenu_track_clicked, track.submenu_track),
1258    
1259      LAST_ENTRY
1260    };
1261    
1262    void menu_create(appdata_t *appdata) {
1263      HildonAppMenu *menu = HILDON_APP_MENU(hildon_app_menu_new());
1264    
1265      /* build menu/submenus */
1266      menu = HILDON_APP_MENU(app_menu_create(appdata, main_menu));
1267      appdata->app_menu_wms   = app_submenu_create(appdata, &submenu_wms);
1268      g_object_ref(appdata->app_menu_wms);
1269      appdata->app_menu_map   = app_submenu_create(appdata, &submenu_map);
1270      g_object_ref(appdata->app_menu_map);
1271      appdata->app_menu_view  = app_submenu_create(appdata, &submenu_view);
1272      g_object_ref(appdata->app_menu_view);
1273      appdata->app_menu_track = app_submenu_create(appdata, &submenu_track);
1274      g_object_ref(appdata->app_menu_track);
1275    
1276      /* enable/disable some entries according to settings */
1277      if(appdata && appdata->settings)
1278        gtk_widget_set_sensitive(appdata->track.menu_item_track_follow_gps,
1279                                 appdata->settings->enable_gps);
1280    
1281      hildon_window_set_app_menu(HILDON_WINDOW(appdata->window), menu);
1282    }
1283    
1284    void menu_cleanup(appdata_t *appdata) {
1285      submenu_cleanup(appdata->app_menu_view);
1286      submenu_cleanup(appdata->app_menu_map);
1287      submenu_cleanup(appdata->app_menu_wms);
1288      submenu_cleanup(appdata->app_menu_track);
1289    }
1290    #endif
1291    
1292  /********************* end of menu **********************/  /********************* end of menu **********************/
1293    
1294  #ifdef UISPECIFIC_MENU_HAS_ACCELS  #ifdef UISPECIFIC_MENU_HAS_ACCELS
# Line 822  void cleanup(appdata_t *appdata) { Line 1342  void cleanup(appdata_t *appdata) {
1342    map_remove_bg_image(appdata->map);    map_remove_bg_image(appdata->map);
1343    
1344    osm_free(&appdata->icon, appdata->osm);    osm_free(&appdata->icon, appdata->osm);
1345      appdata->osm = NULL;
1346    
1347    curl_global_cleanup();    curl_global_cleanup();
1348    
# Line 839  void cleanup(appdata_t *appdata) { Line 1360  void cleanup(appdata_t *appdata) {
1360    
1361    project_free(appdata->project);    project_free(appdata->project);
1362    
1363    if(appdata->menu_item_osm_undo)    if(appdata->menu_item_map_undo)
1364      undo_free(appdata->undo.state);      undo_free(appdata->osm, appdata->undo.state);
1365    
1366      menu_cleanup(appdata);
1367    
1368    puts("everything is gone");    puts("everything is gone");
1369  }  }
# Line 857  gboolean on_window_key_press(GtkWidget * Line 1380  gboolean on_window_key_press(GtkWidget *
1380    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
1381    int handled = FALSE;    int handled = FALSE;
1382    
1383      //  printf("key event with keyval %x\n", event->keyval);
1384    
1385    // the map handles some keys on its own ...    // the map handles some keys on its own ...
1386    switch(event->keyval) {    switch(event->keyval) {
1387    
1388    #if !defined(USE_HILDON) || (MAEMO_VERSION_MAJOR < 5)
1389  #ifdef USE_HILDON  #ifdef USE_HILDON
1390      /* this is in fact a mapping to GDK_F6 */      /* this is in fact a mapping to GDK_F6 */
1391    case HILDON_HARDKEY_FULLSCREEN:    case HILDON_HARDKEY_FULLSCREEN:
# Line 879  gboolean on_window_key_press(GtkWidget * Line 1405  gboolean on_window_key_press(GtkWidget *
1405    
1406      handled = TRUE;      handled = TRUE;
1407      break;      break;
1408    #endif
1409    }    }
1410    
1411    /* forward unprocessed key presses to map */    /* forward unprocessed key presses to map */
# Line 888  gboolean on_window_key_press(GtkWidget * Line 1415  gboolean on_window_key_press(GtkWidget *
1415    return handled;    return handled;
1416  }  }
1417    
1418    #if (MAEMO_VERSION_MAJOR == 5) && !defined(__i386__)
1419    /* get access to zoom buttons */
1420    static void
1421    on_window_realize(GtkWidget *widget, appdata_t *appdata) {
1422      if (widget->window) {
1423        unsigned char value = 1;
1424        Atom hildon_zoom_key_atom =
1425          gdk_x11_get_xatom_by_name("_HILDON_ZOOM_KEY_ATOM"),
1426          integer_atom = gdk_x11_get_xatom_by_name("INTEGER");
1427        Display *dpy =
1428          GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(widget->window));
1429        Window w = GDK_WINDOW_XID(widget->window);
1430    
1431        XChangeProperty(dpy, w, hildon_zoom_key_atom,
1432                        integer_atom, 8, PropModeReplace, &value, 1);
1433      }
1434    }
1435    #endif
1436    
1437    #ifdef FREMANTLE
1438    static GtkWidget *icon_button(appdata_t *appdata, char *icon, GCallback cb,
1439                                  GtkWidget *box) {
1440      /* add zoom-in button */
1441      GtkWidget *but = gtk_button_new();
1442      gtk_button_set_image(GTK_BUTTON(but),
1443                           icon_widget_load(&appdata->icon, icon));
1444      hildon_gtk_widget_set_theme_size(but,
1445                       (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
1446    
1447      if(cb)
1448        g_signal_connect(but, "clicked", G_CALLBACK(cb), appdata);
1449    
1450      gtk_box_pack_start(GTK_BOX(box), but, FALSE, FALSE, 0);
1451      return but;
1452    }
1453    #endif
1454    
1455  int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
1456    appdata_t appdata;    appdata_t appdata;
1457    
# Line 906  int main(int argc, char *argv[]) { Line 1470  int main(int argc, char *argv[]) {
1470    
1471    g_thread_init(NULL);    g_thread_init(NULL);
1472    
   gps_init(&appdata);  
   
1473    gtk_init (&argc, &argv);    gtk_init (&argc, &argv);
1474    
1475      gps_init(&appdata);
1476    
1477  #ifdef USE_HILDON  #ifdef USE_HILDON
1478    printf("Installing osso context for \"org.harbaum." PACKAGE "\"\n");    printf("Installing osso context for \"org.harbaum." PACKAGE "\"\n");
1479    appdata.osso_context = osso_initialize("org.harbaum."PACKAGE,    appdata.osso_context = osso_initialize("org.harbaum."PACKAGE,
# Line 926  int main(int argc, char *argv[]) { Line 1490  int main(int argc, char *argv[]) {
1490    g_set_application_name("OSM2Go");    g_set_application_name("OSM2Go");
1491    
1492    /* Create HildonWindow and set it to HildonProgram */    /* Create HildonWindow and set it to HildonProgram */
1493    #if MAEMO_VERSION_MAJOR < 5
1494    appdata.window = HILDON_WINDOW(hildon_window_new());    appdata.window = HILDON_WINDOW(hildon_window_new());
1495    #else
1496      appdata.window = HILDON_WINDOW(hildon_stackable_window_new());
1497    #endif
1498    hildon_program_add_window(appdata.program, appdata.window);    hildon_program_add_window(appdata.program, appdata.window);
1499    
1500      /* try to enable the zoom buttons. don't do this on x86 as it breaks */
1501      /* at runtime with cygwin x */
1502    #if (MAEMO_VERSION_MAJOR == 5) && !defined(__i386__)
1503      g_signal_connect(G_OBJECT(appdata.window), "realize",
1504                       G_CALLBACK(on_window_realize), &appdata);
1505    #endif // MAEMO_VERSION
1506    
1507  #else  #else
1508    /* Create a Window. */    /* Create a Window. */
1509    appdata.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);    appdata.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
# Line 971  int main(int argc, char *argv[]) { Line 1547  int main(int argc, char *argv[]) {
1547    }    }
1548    
1549    gtk_box_pack_start(GTK_BOX(vbox), map, TRUE, TRUE, 0);    gtk_box_pack_start(GTK_BOX(vbox), map, TRUE, TRUE, 0);
1550    
1551      /* fremantle has seperate zoom/details buttons on the right screen side */
1552    #if !defined(FREMANTLE) && (defined(ZOOM_BUTTONS) || defined(DETAIL_POPUP))
1553      GtkWidget *zhbox = gtk_hbox_new(FALSE, 0);
1554      gtk_box_pack_start_defaults(GTK_BOX(zhbox), statusbar_new(&appdata));
1555    #endif
1556    
1557    #if !defined(FREMANTLE) && defined(DETAIL_POPUP)
1558      /* ---- detail popup ---- */
1559      appdata.btn_detail_popup = gtk_button_new();
1560      gtk_button_set_image(GTK_BUTTON(appdata.btn_detail_popup),
1561            gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
1562      g_signal_connect(appdata.btn_detail_popup, "clicked",
1563                       G_CALLBACK(scale_popup), &appdata);
1564      gtk_box_pack_start(GTK_BOX(zhbox), appdata.btn_detail_popup, FALSE, FALSE, 0);
1565    #endif
1566    
1567    #if !defined(FREMANTLE) && defined(ZOOM_BUTTONS)
1568      /* ---- add zoom out button right of statusbar ---- */
1569      appdata.btn_zoom_out = gtk_button_new();
1570      gtk_button_set_image(GTK_BUTTON(appdata.btn_zoom_out),
1571            gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_MENU));
1572      g_signal_connect(appdata.btn_zoom_out, "clicked",
1573                       G_CALLBACK(cb_menu_zoomout), &appdata);
1574      gtk_box_pack_start(GTK_BOX(zhbox), appdata.btn_zoom_out, FALSE, FALSE, 0);
1575    
1576      /* ---- add zoom in button right of statusbar ---- */
1577      appdata.btn_zoom_in = gtk_button_new();
1578      gtk_button_set_image(GTK_BUTTON(appdata.btn_zoom_in),
1579            gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_MENU));
1580      g_signal_connect(appdata.btn_zoom_in, "clicked",
1581                       G_CALLBACK(cb_menu_zoomin), &appdata);
1582      gtk_box_pack_start(GTK_BOX(zhbox), appdata.btn_zoom_in, FALSE, FALSE, 0);
1583    #endif
1584    
1585    #if !defined(FREMANTLE) && (defined(ZOOM_BUTTONS) || defined(DETAIL_POPUP))
1586      gtk_box_pack_start(GTK_BOX(vbox), zhbox, FALSE, FALSE, 0);
1587    #else
1588    gtk_box_pack_start(GTK_BOX(vbox), statusbar_new(&appdata), FALSE, FALSE, 0);    gtk_box_pack_start(GTK_BOX(vbox), statusbar_new(&appdata), FALSE, FALSE, 0);
1589    #endif
1590    
1591  #ifndef PORTRAIT  #ifndef PORTRAIT
1592    gtk_box_pack_start(GTK_BOX(hbox), iconbar_new(&appdata), FALSE, FALSE, 0);    gtk_box_pack_start(GTK_BOX(hbox), iconbar_new(&appdata), FALSE, FALSE, 0);
1593  #endif  #endif
   gtk_box_pack_start(GTK_BOX(hbox), gtk_vseparator_new(), FALSE, FALSE, 0);  
1594    gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);    gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1595    
1596    #ifdef FREMANTLE
1597      /* fremantle has a set of buttons on the right screen side as well */
1598      vbox = gtk_vbox_new(FALSE, 0);
1599    
1600      GtkWidget *ivbox = gtk_vbox_new(FALSE, 0);
1601      appdata.btn_zoom_in =
1602        icon_button(&appdata, "zoomin_thumb",   G_CALLBACK(cb_menu_zoomin), ivbox);
1603      appdata.btn_zoom_out =
1604        icon_button(&appdata, "zoomout_thumb",  G_CALLBACK(cb_menu_zoomout), ivbox);
1605      gtk_box_pack_start(GTK_BOX(vbox), ivbox, FALSE, FALSE, 0);
1606    
1607      ivbox = gtk_vbox_new(FALSE, 0);
1608      icon_button(&appdata, "detailup_thumb",   G_CALLBACK(cb_menu_view_detail_inc), ivbox);
1609      icon_button(&appdata, "detaildown_thumb", G_CALLBACK(cb_menu_view_detail_dec), ivbox);
1610      gtk_box_pack_start(GTK_BOX(vbox), ivbox, TRUE, FALSE, 0);
1611    
1612      ivbox = gtk_vbox_new(FALSE, 0);
1613      GtkWidget *ok = icon_button(&appdata, "ok_thumb", NULL, ivbox);
1614      GtkWidget *cancel = icon_button(&appdata, "cancel_thumb", NULL, ivbox);
1615      iconbar_register_buttons(&appdata, ok, cancel);
1616      gtk_box_pack_start(GTK_BOX(vbox), ivbox, FALSE, FALSE, 0);
1617    
1618      gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
1619    #endif // FREMANTLE
1620    
1621    gtk_box_pack_start(GTK_BOX(appdata.vbox), hbox, TRUE, TRUE, 0);    gtk_box_pack_start(GTK_BOX(appdata.vbox), hbox, TRUE, TRUE, 0);
1622    
1623    gtk_container_add(GTK_CONTAINER(appdata.window), appdata.vbox);    gtk_container_add(GTK_CONTAINER(appdata.window), appdata.vbox);
# Line 989  int main(int argc, char *argv[]) { Line 1628  int main(int argc, char *argv[]) {
1628    
1629    /* let gtk do its thing before loading the data, */    /* let gtk do its thing before loading the data, */
1630    /* so the user sees something */    /* so the user sees something */
1631    while(gtk_events_pending()) {    while(gtk_events_pending())
     putchar('.');  
1632      gtk_main_iteration();      gtk_main_iteration();
   }  
1633    
1634    /* load project if one is specified in the settings */    /* load project if one is specified in the settings */
1635    if(appdata.settings->project)    if(appdata.settings->project)
# Line 1000  int main(int argc, char *argv[]) { Line 1637  int main(int argc, char *argv[]) {
1637    
1638    main_ui_enable(&appdata);    main_ui_enable(&appdata);
1639    
1640    /* ------------ jump into main loop ---------------- */    /* start GPS if enabled by config */
1641      if(appdata.settings && appdata.settings->enable_gps)
1642        track_enable_gps(&appdata, TRUE);
1643    
1644      /* again let the ui do its thing */
1645      while(gtk_events_pending())
1646        gtk_main_iteration();
1647    
1648      /* start to interact with the user now that the gui is running */
1649      if(appdata.settings->first_run_demo) {
1650        messagef(GTK_WIDGET(appdata.window), _("Welcome to OSM2Go"),
1651                 _("This is the first time you run OSM2Go. "
1652                   "A demo project has been loaded to get you "
1653                   "started. You can play around with this demo as much "
1654                   "as you like. However, you cannot upload or download "
1655                   "the demo project.\n\n"
1656                   "In order to start working on real data you'll have "
1657                   "to setup a new project and enter your OSM user name "
1658                   "and password. You'll then be able to download the "
1659                   "latest data from OSM and upload your changes into "
1660                   "the OSM main database."
1661                   ));
1662      }
1663    
1664      /* ------------ jump into main loop ---------------- */
1665    gtk_main();    gtk_main();
1666    
1667    puts("gtk_main() left");    puts("gtk_main() left");
1668    
1669    track_save(appdata.project, appdata.track.track);    track_save(appdata.project, appdata.track.track);
1670      track_clear(&appdata, appdata.track.track);
1671      appdata.track.track = NULL;
1672    
1673    /* save a diff if there are dirty entries */    /* save a diff if there are dirty entries */
1674    diff_save(appdata.project, appdata.osm);    diff_save(appdata.project, appdata.osm);

Legend:
Removed from v.101  
changed lines
  Added in v.281