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

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