--- trunk/src/main.c 2009/07/05 17:38:06 21 +++ trunk/src/main.c 2009/09/16 13:45:10 113 @@ -138,39 +138,50 @@ gtk_widget_show_all (GTK_WIDGET(dialog)); if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) { char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + if(filename) { + gpx_dialog_t *dialog = gpx_busy_dialog_new(GTK_WIDGET(appdata->window)); - gpx_dialog_t *dialog = gpx_busy_dialog_new(GTK_WIDGET(appdata->window)); - - if(!whole_dir) - gpx = gpx_parse(dialog, filename); - else { - /* cur trailing '/' if present */ - if(strlastchr(filename) == '/') - filename[strlen(filename)] = 0; - - gpx = gpx_parse_dir(dialog, filename); - } - - gpx_busy_dialog_destroy(dialog); - - /* save path if gpx was successfully loaded */ - if(gpx) { - char *r = strrchr(filename, '/'); - - /* there is a delimiter, use everything left of it as path */ - if(r && !whole_dir) { - *r = 0; - if(appdata->path) free(appdata->path); - appdata->path = strdup(filename); - /* restore path ... just in case ... */ - *r = '/'; + if(!whole_dir) + gpx = gpx_parse(dialog, filename); + else { + /* cur trailing '/' if present */ + if(strlastchr(filename) == '/') + filename[strlen(filename)] = 0; + + gpx = gpx_parse_dir(dialog, filename); } + + gpx_busy_dialog_destroy(dialog); + + /* save path if gpx was successfully loaded */ + if(gpx) { + char *r = strrchr(filename, '/'); + + /* there is a delimiter, use everything left of it as path */ + if(r && !whole_dir) { + *r = 0; + if(appdata->path) free(appdata->path); + appdata->path = strdup(filename); + /* restore path ... just in case ... */ + *r = '/'; + } + + if(whole_dir) + appdata->path = strdup(filename); + } else + errorf(_("Load error")); - if(whole_dir) - appdata->path = strdup(filename); + g_free (filename); + } else { +#ifndef USE_MAEMO + errorf(_("Error accessing the file.")); +#else + errorf(_("Error accessing the file. This may happen if the file " + "resides on a remote file system. Please copy the file onto " + "the device (e.g. onto the memory card) and try again.")); +#endif } - - g_free (filename); } gtk_widget_destroy (dialog); @@ -202,6 +213,12 @@ GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model(treeview); +#ifdef USE_MAEMO + /* check if a cache is already selected and ignore click if yes */ + /* (was probably a double click) */ + if(appdata->cur_cache) return; +#endif + if(gtk_tree_model_get_iter(model, &iter, path)) { cache_t *cache; gtk_tree_model_get(model, &iter, CACHELIST_COL_DATA, &cache, -1); @@ -587,7 +604,7 @@ g_object_set_data(G_OBJECT(window), "cur_view", appdata->cur_view); appdata->cur_gpx = gpx; - char *title = g_strdup_printf("GPXView - %s", gpx->name); + char *title = g_strdup_printf("%s - GPXView", gpx->name); gtk_window_set_title(GTK_WINDOW(window), title); g_free(title); @@ -713,6 +730,12 @@ GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model(treeview); +#ifdef USE_MAEMO + /* check if a cache is already selected and ignore click if yes */ + /* (was probably a double click) */ + if(appdata->cur_gpx) return; +#endif + if (gtk_tree_model_get_iter(model, &iter, path)) { gpx_t *gpx; gtk_tree_model_get(model, &iter, GPXLIST_COL_DATA, &gpx, -1); @@ -957,7 +980,7 @@ GtkTreeIter iter; gtk_list_store_append(appdata->gpxstore, &iter); gpxlist_set(appdata->gpxstore, &iter, gpx); - + if(gpx == sel_gpx) { sel_iter = iter; sel_iter_valid = TRUE; @@ -1017,12 +1040,25 @@ /******************** begin of menu *********************/ +typedef struct { + appdata_t *appdata; + GtkWidget *dialog; +} about_context_t; + +#ifdef ENABLE_BROWSER_INTERFACE +void on_paypal_button_clicked(GtkButton *button, about_context_t *context) { + gtk_dialog_response(GTK_DIALOG(context->dialog), GTK_RESPONSE_ACCEPT); + browser_url(context->appdata, + "https://www.paypal.com/cgi-bin/webscr" + "?cmd=_s-xclick&hosted_button_id=7400558"); +} +#endif + static void cb_menu_about(GtkWidget *window, gpointer data) { - GtkAboutDialog *about = GTK_ABOUT_DIALOG(gtk_about_dialog_new()); + about_context_t context; - gtk_about_dialog_set_name(about, "GPXView"); - gtk_about_dialog_set_version(about, VERSION); + context.appdata = (appdata_t *)data; #ifdef ENABLE_LIBLOCATION char *uses = "uses liblocation"; @@ -1032,25 +1068,46 @@ char *uses = "uses gpsd"; #endif - char *str = g_strdup_printf("%s\n\n(%s)", - _("GPXView (c) 2008-2009 by\n" - "Till Harbaum \n" - "Mailing list: gpxview-users@garage.maemo.org"), - _(uses) - ); - - gtk_about_dialog_set_copyright(about, str); - g_free(str); - - gtk_about_dialog_set_website(about, - _("http://www.harbaum.org/till/maemo")); - - gtk_about_dialog_set_comments(about, - _("Geocaching.com GPX file viewer")); - - gtk_widget_show_all(GTK_WIDGET(about)); - gtk_dialog_run(GTK_DIALOG(about)); - gtk_widget_destroy(GTK_WIDGET(about)); + const gchar *authors[] = { + "Till Harbaum ", + "John Stowers ", + NULL }; + + context.dialog = g_object_new(GTK_TYPE_ABOUT_DIALOG, + "name", "GPXView", + "version", VERSION, + "copyright", _("Copyright 2008-2009"), + "authors", authors, + "website", _("http://www.harbaum.org/till/maemo"), + "comments", _(uses), + NULL); + +#ifdef ENABLE_BROWSER_INTERFACE + /* add a way to donate to the project */ + GtkWidget *alignment = gtk_alignment_new(0.5, 0, 0, 0); + + GtkWidget *hbox = gtk_hbox_new(FALSE, 8); + gtk_box_pack_start(GTK_BOX(hbox), + gtk_label_new(_("Do you like GPXView?")), + FALSE, FALSE, 0); + + GtkWidget *button = gtk_button_new(); + gtk_button_set_image(GTK_BUTTON(button), + icon_get_widget(ICON_MISC, 8)); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); + g_signal_connect(button, "clicked", + G_CALLBACK(on_paypal_button_clicked), &context); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(alignment), hbox); + gtk_box_pack_start_defaults(GTK_BOX((GTK_DIALOG(context.dialog))->vbox), + alignment); + + gtk_widget_show_all(alignment); +#endif + + gtk_dialog_run(GTK_DIALOG(context.dialog)); + gtk_widget_destroy(context.dialog); } #if defined(USE_MAEMO) && defined(HILDON_HELP) @@ -1433,7 +1490,7 @@ gtk_widget_destroy(dialog); } -void on_window_destroy (GtkWidget *widget, gpointer data); +static void on_window_destroy (GtkWidget *widget, gpointer data); #ifndef USE_MAEMO static void @@ -1493,9 +1550,6 @@ cb_menu_export_log(GtkWidget *widget, gpointer data) { appdata_t *appdata = (appdata_t*)data; notes_log_export(appdata); -#ifdef USE_STACKABLE_WINDOW - hildon_window_stack_pop_1 (hildon_window_stack_get_default()); -#endif } #ifdef USE_MAEMO @@ -1503,9 +1557,6 @@ cb_menu_export_mmpoi(GtkWidget *widget, gpointer data) { appdata_t *appdata = (appdata_t*)data; mmpoi_export(appdata); -#ifdef USE_STACKABLE_WINDOW - hildon_window_stack_pop_1 (hildon_window_stack_get_default()); -#endif } #endif @@ -1513,136 +1564,158 @@ cb_menu_export_garmin(GtkWidget *widget, gpointer data) { appdata_t *appdata = (appdata_t*)data; garmin_export(appdata); -#ifdef USE_STACKABLE_WINDOW - hildon_window_stack_pop_1 (hildon_window_stack_get_default()); -#endif } +#ifdef ENABLE_OSM_GPS_MAP +static void +cb_menu_map(GtkWidget *window, gpointer data) { + map((appdata_t *)data); +} +#endif + static void cb_menu_geomath(GtkWidget *window, gpointer data) { geomath_dialog((appdata_t *)data); -#ifdef USE_STACKABLE_WINDOW - hildon_window_stack_pop_1 (hildon_window_stack_get_default()); -#endif } static void cb_menu_geotext(GtkWidget *window, gpointer data) { geotext_dialog((appdata_t *)data); -#ifdef USE_STACKABLE_WINDOW - hildon_window_stack_pop_1 (hildon_window_stack_get_default()); -#endif } static void cb_menu_precpos(GtkWidget *window, gpointer data) { precise_position((appdata_t *)data); -#ifdef USE_STACKABLE_WINDOW - hildon_window_stack_pop_1 (hildon_window_stack_get_default()); -#endif } #ifdef USE_STACKABLE_WINDOW -static GtkWidget *export_menu_create(appdata_t *appdata) { - GtkWidget *button; - HildonAppMenu *menu = HILDON_APP_MENU(hildon_app_menu_new()); - - button = hildon_button_new_with_text( - HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH, - HILDON_BUTTON_ARRANGEMENT_VERTICAL, - _("Export to Maemo Mapper"), - _("Save a Maemo Mapper POI file")); - g_signal_connect(button, "clicked", - G_CALLBACK(cb_menu_export_mmpoi), appdata); - hildon_app_menu_append(menu, GTK_BUTTON(button)); +typedef struct { + char *label, *desc; + GtkSignalFunc activate_cb; +} menu_entry_t; - button = hildon_button_new_with_text( - HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH, - HILDON_BUTTON_ARRANGEMENT_VERTICAL, - _("Export Field Notes"), - _("Save a Garmin Field Notes file")); - g_signal_connect(button, "clicked", - G_CALLBACK(cb_menu_export_log), appdata); - hildon_app_menu_append(menu, GTK_BUTTON(button)); +typedef struct { + const char *title; + const menu_entry_t *menu; + int len; +} submenu_t; - button = hildon_button_new_with_text( - HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH, - HILDON_BUTTON_ARRANGEMENT_VERTICAL, - _("Export Garmin GPX"), - _("Save modified waypoints in GPX file")); - g_signal_connect(button, "clicked", - G_CALLBACK(cb_menu_export_garmin), appdata); - hildon_app_menu_append(menu, GTK_BUTTON(button)); +#define COLUMNS 1 - gtk_widget_show_all(GTK_WIDGET(menu)); +void on_submenu_entry_clicked(GtkButton *button, GtkWidget *menu) { - return GTK_WIDGET(menu); + /* force closing of submenu dialog */ + gtk_dialog_response(GTK_DIALOG(menu), GTK_RESPONSE_NONE); + gtk_widget_hide(menu); + + /* let gtk clean up */ + while(gtk_events_pending()) + gtk_main_iteration(); } -/* the export submenu */ -void on_export_clicked(GtkButton *button, appdata_t *appdata) { - if(!appdata->export_menu) - appdata->export_menu = export_menu_create(appdata); +static GtkWidget *app_submenu_create(appdata_t *appdata, + const submenu_t *submenu) { - /* draw a popup menu */ - hildon_app_menu_popup(HILDON_APP_MENU(appdata->export_menu), - GTK_WINDOW(hildon_window_stack_peek( - hildon_window_stack_get_default()))); -} + /* create a oridinary dialog box */ + GtkWidget *dialog = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(dialog), _(submenu->title)); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + gtk_window_set_transient_for(GTK_WINDOW(dialog), + GTK_WINDOW(appdata->window)); + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); -static GtkWidget *tools_menu_create(appdata_t *appdata) { - GtkWidget *button; - HildonAppMenu *menu = HILDON_APP_MENU(hildon_app_menu_new()); + GtkWidget *table = gtk_table_new(submenu->len/COLUMNS, COLUMNS, TRUE); + int x = 0, y = 0; - /* the following doesn't have an effect */ - // gtk_window_set_title(GTK_WINDOW(menu), "Tools"); + const menu_entry_t *menu_entries = submenu->menu; + while(menu_entries->label) { + GtkWidget *button = NULL; - button = hildon_button_new_with_text( + button = hildon_button_new_with_text( HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH, HILDON_BUTTON_ARRANGEMENT_VERTICAL, - _("Geomath"), - _("Geocoordinate calculation")); - g_signal_connect(button, "clicked", - G_CALLBACK(cb_menu_geomath), appdata); - hildon_app_menu_append(menu, GTK_BUTTON(button)); + _(menu_entries->label), _(menu_entries->desc)); + /* try to center both texts */ + hildon_button_set_title_alignment(HILDON_BUTTON(button), 0.5, 0.5); + hildon_button_set_value_alignment(HILDON_BUTTON(button), 0.5, 0.5); - button = hildon_button_new_with_text( - HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH, - HILDON_BUTTON_ARRANGEMENT_VERTICAL, - _("Geotext"), - _("Text analysis")); - g_signal_connect(button, "clicked", - G_CALLBACK(cb_menu_geotext), appdata); - hildon_app_menu_append(menu, GTK_BUTTON(button)); - + g_signal_connect(button, "clicked", + G_CALLBACK(on_submenu_entry_clicked), dialog); + + g_signal_connect(button, "clicked", + menu_entries->activate_cb, appdata); + + gtk_table_attach_defaults(GTK_TABLE(table), button, x, x+1, y, y+1); + + x++; + if(x == COLUMNS) { x = 0; y++; } - button = hildon_button_new_with_text( - HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH, - HILDON_BUTTON_ARRANGEMENT_VERTICAL, - _("Precise Position"), - _("Calculate a precise GPS position")); - g_signal_connect(button, "clicked", - G_CALLBACK(cb_menu_precpos), appdata); - hildon_app_menu_append(menu, GTK_BUTTON(button)); + menu_entries++; + } - gtk_widget_show_all(GTK_WIDGET(menu)); + gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), table); - return GTK_WIDGET(menu); + return dialog; } +/* popup the dialog shaped submenu */ +static void submenu_popup(GtkWidget *menu) { + gtk_widget_show_all(menu); + gtk_dialog_run(GTK_DIALOG(menu)); + gtk_widget_hide(menu); +} + +static void submenu_cleanup(GtkWidget *menu) { + gtk_widget_destroy(menu); +} + +static const menu_entry_t submenu_export_entries[] = { + { "Export to Maemo Mapper" , "Save a Maemo Mapper POI file", + G_CALLBACK(cb_menu_export_mmpoi) }, + { "Export Field Notes", "Save a Garmin Field Notes file", + G_CALLBACK(cb_menu_export_log) }, + { "Export Garmin GPX", "Save modified waypoints in GPX file", + G_CALLBACK(cb_menu_export_garmin) }, + { NULL, NULL, NULL } +}; + +static const submenu_t submenu_export = { + "Export", submenu_export_entries, + sizeof(submenu_export_entries)/sizeof(menu_entry_t)-1 +}; + +/* the export submenu */ +void on_export_clicked(GtkButton *button, appdata_t *appdata) { + if(!appdata->export_menu) + appdata->export_menu = app_submenu_create(appdata, &submenu_export); + + submenu_popup(appdata->export_menu); +} + +static const menu_entry_t submenu_tools_entries[] = { + { "Geomath", "Geocoordinate calculation", + G_CALLBACK(cb_menu_geomath) }, + { "Geotext", "Text analysis", + G_CALLBACK(cb_menu_geotext) }, + { "Precise Position", "Calculate a precise GPS position", + G_CALLBACK(cb_menu_precpos) }, + { NULL, NULL, NULL } +}; + +static const submenu_t submenu_tools = { + "Tools", submenu_tools_entries, + sizeof(submenu_tools_entries)/sizeof(menu_entry_t)-1 +}; + /* the tools submenu */ void on_tools_clicked(GtkButton *button, appdata_t *appdata) { if(!appdata->tools_menu) - appdata->tools_menu = tools_menu_create(appdata); + appdata->tools_menu = app_submenu_create(appdata, &submenu_tools); - /* draw a popup menu */ - hildon_app_menu_popup(HILDON_APP_MENU(appdata->tools_menu), - GTK_WINDOW(hildon_window_stack_peek( - hildon_window_stack_get_default()))); + submenu_popup(appdata->tools_menu); } - HildonAppMenu *menu_create(appdata_t *appdata, int mode) { GtkWidget *button; HildonAppMenu *menu = HILDON_APP_MENU(hildon_app_menu_new()); @@ -1668,9 +1741,7 @@ g_signal_connect_after(button, "clicked", G_CALLBACK(cb_menu_adddir), appdata); hildon_app_menu_append(menu, GTK_BUTTON(button)); - } - if(mode == MENU_GPXLIST) { button = gtk_button_new_with_label(_("Export")); g_signal_connect_after(button, "clicked", G_CALLBACK(on_export_clicked), appdata); @@ -1687,6 +1758,15 @@ G_CALLBACK(on_tools_clicked), appdata); hildon_app_menu_append(menu, GTK_BUTTON(button)); +#ifdef ENABLE_OSM_GPS_MAP + if((mode == MENU_GPXLIST) || (mode == MENU_CACHELIST)) { + button = gtk_button_new_with_label(_("Map")); + g_signal_connect_after(button, "clicked", + G_CALLBACK(cb_menu_map), appdata); + hildon_app_menu_append(menu, GTK_BUTTON(button)); + } +#endif + #ifdef HILDON_HELP button = gtk_button_new_with_label(_("Help")); g_signal_connect_after(button, "clicked", @@ -1799,6 +1879,13 @@ gtk_menu_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); +#ifdef ENABLE_OSM_GPS_MAP + item = gtk_menu_item_new_with_label( _("Map") ); + gtk_menu_append(GTK_MENU_SHELL(menu), item); + g_signal_connect(item, "activate", + GTK_SIGNAL_FUNC(cb_menu_map), appdata); +#endif + item = gtk_menu_item_new_with_label(_("Tools")); gtk_menu_append(GTK_MENU_SHELL(menu), item); submenu = gtk_menu_new(); @@ -1863,6 +1950,11 @@ if(appdata->image_path) free(appdata->image_path); if(appdata->search_str) free(appdata->search_str); +#ifdef USE_STACKABLE_WINDOW + if(appdata->export_menu) submenu_cleanup(appdata->export_menu); + if(appdata->tools_menu) submenu_cleanup(appdata->tools_menu); +#endif + gnome_vfs_shutdown(); icons_free(); gps_release(appdata); @@ -1891,7 +1983,7 @@ puts("everything is gone"); } -void on_window_destroy (GtkWidget *widget, gpointer data) { +static void on_window_destroy (GtkWidget *widget, gpointer data) { appdata_t *appdata = (appdata_t*)data; gconf_save_state(appdata); @@ -2234,7 +2326,6 @@ appdata.vbox = gtk_vbox_new(FALSE, 2); gtk_container_add(GTK_CONTAINER(appdata.window), appdata.vbox); - #ifndef USE_STACKABLE_WINDOW menu_create(&appdata); #else