From b73f29fea3ae88a06d8f773a6d48510520c127f0 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 9 Sep 2012 09:06:44 -0700 Subject: First cut of adding a default file name The default file name is OS specific and tries to follow the customs on each of the OSs. It can be configured through the preferences dialog. On MacOS we get a strange warning which appears to be a well documented Gtk bug on MacOS. Signed-off-by: Dirk Hohndel --- display-gtk.h | 2 -- dive.h | 2 ++ gtk-gui.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- linux.c | 21 +++++++++++++ macos.c | 19 ++++++++++++ main.c | 11 ++++++- windows.c | 24 +++++++++++++++ 7 files changed, 168 insertions(+), 6 deletions(-) diff --git a/display-gtk.h b/display-gtk.h index dd7e2c4a0..e03861d39 100644 --- a/display-gtk.h +++ b/display-gtk.h @@ -50,8 +50,6 @@ extern const char *subsurface_icon_name(void); extern void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar, GtkWidget *vbox, GtkUIManager *ui_manager); -extern const char *divelist_font; - extern visible_cols_t visible_cols; extern const char *divelist_font; diff --git a/dive.h b/dive.h index 29814c34e..746b94093 100644 --- a/dive.h +++ b/dive.h @@ -459,6 +459,8 @@ const char *monthname(int mon); #define FIVE_STARS UTF8_BLACKSTAR UTF8_BLACKSTAR UTF8_BLACKSTAR UTF8_BLACKSTAR UTF8_BLACKSTAR extern const char *star_strings[]; +extern const char *default_filename; +extern const char *subsurface_default_filename(void); #define AIR_PERMILLE 209 #endif /* DIVE_H */ diff --git a/gtk-gui.c b/gtk-gui.c index a2f130ac2..1d5fc4cc9 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "dive.h" #include "divelist.h" @@ -26,6 +27,7 @@ GtkWidget *notebook; int error_count; const char *divelist_font; +const char *default_filename; struct units output_units; @@ -173,8 +175,8 @@ static void file_open(GtkWidget *w, gpointer data) } /* return the path and the file component contained in the full path */ -static char *path_and_file(char *pathin, char **fileout) { - char *slash = pathin, *next; +static char *path_and_file(const char *pathin, char **fileout) { + const char *slash = pathin, *next; char *result; size_t len, n; @@ -239,9 +241,24 @@ static void file_save_as(GtkWidget *w, gpointer data) static void file_save(GtkWidget *w, gpointer data) { + const char *current_default; + if (!existing_filename) return file_save_as(w, data); + current_default = subsurface_default_filename(); + if (strcmp(existing_filename, current_default) == 0) { + /* if we are using the default filename the directory + * that we are creating the file in may not exist */ + char *current_def_dir, *current_def_file; + struct stat sb; + + current_def_dir = path_and_file(existing_filename, ¤t_def_file); + if (stat(current_def_dir, &sb) != 0) { + mkdir(current_def_dir, S_IRUSR | S_IWUSR); + } + } + free((void *)current_default); save_dives(existing_filename); mark_divelist_changed(FALSE); } @@ -437,10 +454,66 @@ static void event_toggle(GtkWidget *w, gpointer _data) *plot_ev = GTK_TOGGLE_BUTTON(w)->active; } +static void pick_default_file(GtkWidget *w, GtkButton *button) +{ + GtkWidget *fs_dialog; + const char *current_default, *new_default = NULL; + char *current_def_file, *current_def_dir; + GtkFileFilter *filter; + struct stat sb; + gboolean need_rmdir = FALSE; + + fs_dialog = gtk_file_chooser_dialog_new("Choose Default XML File", + GTK_WINDOW(main_window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + NULL); + current_default = subsurface_default_filename(); + current_def_dir = path_and_file(current_default, ¤t_def_file); + free((void *)current_default); + /* it's possible that the directory doesn't exist (especially for the default) + * For gtk's file select box to make sense we create it if needed and then remove + * it after the dialog has run */ + if (stat(current_def_dir, &sb) != 0) { + if (mkdir(current_def_dir, S_IRUSR | S_IWUSR) == 0) + need_rmdir = TRUE; + } + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs_dialog), current_def_dir); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fs_dialog), current_def_file); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fs_dialog), FALSE); + filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filter, "*.xml"); + gtk_file_filter_add_pattern(filter, "*.XML"); + gtk_file_filter_add_pattern(filter, "*.sda"); + gtk_file_filter_add_pattern(filter, "*.SDA"); + gtk_file_filter_add_mime_type(filter, "text/xml"); + gtk_file_filter_set_name(filter, "XML file"); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fs_dialog), filter); + gtk_widget_show_all(fs_dialog); + if (gtk_dialog_run(GTK_DIALOG(fs_dialog)) == GTK_RESPONSE_ACCEPT) { + GSList *list; + + list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(fs_dialog)); + if (g_slist_length(list) == 1) { + new_default = strdup(list->data); + } + g_slist_free(list); + if (new_default) + gtk_button_set_label(button, new_default); + } + if (need_rmdir) + rmdir(current_def_dir); + free(current_def_dir); + free(current_def_file); + gtk_widget_destroy(fs_dialog); +} + static void preferences_dialog(GtkWidget *w, gpointer data) { int result; GtkWidget *dialog, *font, *frame, *box, *vbox, *button; + const char *current_default, *new_default; menu_units = output_units; @@ -541,6 +614,15 @@ static void preferences_dialog(GtkWidget *w, gpointer data) gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(autogroup_toggle), NULL); + frame = gtk_frame_new("Default XML Data File"); + gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 5); + box = gtk_hbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER(frame), box); + current_default = subsurface_default_filename(); + button = gtk_button_new_with_label(current_default); + g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(pick_default_file), button); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); + gtk_widget_show_all(dialog); result = gtk_dialog_run(GTK_DIALOG(dialog)); if (result == GTK_RESPONSE_ACCEPT) { @@ -569,11 +651,18 @@ static void preferences_dialog(GtkWidget *w, gpointer data) subsurface_set_conf("OTU", PREF_BOOL, BOOL_TO_PTR(visible_cols.otu)); subsurface_set_conf("divelist_font", PREF_STRING, divelist_font); subsurface_set_conf("autogroup", PREF_BOOL, BOOL_TO_PTR(autogroup)); + new_default = strdup(gtk_button_get_label(GTK_BUTTON(button))); + if (strcmp(current_default, new_default)) { + subsurface_set_conf("default_filename", PREF_STRING, new_default); + free((void *)default_filename); + default_filename = new_default; + } /* Flush the changes out to the system */ subsurface_flush_conf(); } gtk_widget_destroy(dialog); + free((void *)current_default); } static void create_toggle(const char* label, int *on, void *_data) @@ -873,8 +962,8 @@ void init_ui(int *argcp, char ***argvp) visible_cols.sac = PTR_TO_BOOL(subsurface_get_conf("SAC", PREF_BOOL)); divelist_font = subsurface_get_conf("divelist_font", PREF_STRING); - autogroup = PTR_TO_BOOL(subsurface_get_conf("autogroup", PREF_BOOL)); + default_filename = subsurface_get_conf("default_filename", PREF_STRING); default_dive_computer_vendor = subsurface_get_conf("dive_computer_vendor", PREF_STRING); default_dive_computer_product = subsurface_get_conf("dive_computer_product", PREF_STRING); diff --git a/linux.c b/linux.c index 42a3c9f5f..8d9f6f8ce 100644 --- a/linux.c +++ b/linux.c @@ -1,7 +1,10 @@ /* linux.c */ /* implements Linux specific functions */ +#include "dive.h" #include "display-gtk.h" #include +#include + #define DIVELIST_DEFAULT_FONT "Sans 8" GConfClient *gconf; @@ -63,6 +66,24 @@ const char *subsurface_icon_name() return "subsurface.svg"; } +const char *subsurface_default_filename() +{ + if (default_filename) { + return default_filename; + } else { + const char *home, *user; + char *buffer; + int len; + + home = g_get_home_dir(); + user = g_get_user_name(); + len = strlen(home) + strlen(user) + 17; + buffer = malloc(len); + snprintf(buffer, len, "%s/subsurface/%s.xml", home, user); + return buffer; + } +} + void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar, GtkWidget *vbox, GtkUIManager *ui_manager) { diff --git a/macos.c b/macos.c index 20445c808..fbf399890 100644 --- a/macos.c +++ b/macos.c @@ -1,5 +1,6 @@ /* macos.c */ /* implements Mac OS X specific functions */ +#include "dive.h" #include "display-gtk.h" #include #include @@ -85,6 +86,24 @@ const char *subsurface_icon_name() return path; } +const char *subsurface_default_filename() +{ + if (default_filename) { + return default_filename; + } else { + const char *home, *user; + char *buffer; + int len; + + home = g_get_home_dir(); + user = g_get_user_name(); + len = strlen(home) + strlen(user) + 45; + buffer = malloc(len); + snprintf(buffer, len, "%s/Library/Application Support/Subsurface/%s.xml", home, user); + return buffer; + } +} + void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar, GtkWidget *vbox, GtkUIManager *ui_manager) { diff --git a/main.c b/main.c index 2489473b9..a2c24ec99 100644 --- a/main.c +++ b/main.c @@ -211,6 +211,7 @@ void renumber_dives(int nr) int main(int argc, char **argv) { int i; + gboolean no_filenames = TRUE; output_units = SI_units; @@ -225,6 +226,7 @@ int main(int argc, char **argv) parse_argument(a); continue; } + no_filenames = FALSE; GError *error = NULL; parse_file(a, &error); @@ -235,7 +237,14 @@ int main(int argc, char **argv) error = NULL; } } - + if (no_filenames) { + GError *error = NULL; + const char *filename = subsurface_default_filename(); + parse_file(filename, &error); + /* don't report errors - this file may not exist, but make + sure we remember this as the filename in use */ + set_filename(filename); + } report_dives(imported); run_ui(); diff --git a/windows.c b/windows.c index 29ef6122e..87bcaf6bd 100644 --- a/windows.c +++ b/windows.c @@ -1,7 +1,9 @@ /* windows.c */ /* implements Windows specific functions */ +#include "dive.h" #include "display-gtk.h" #include +#include #define DIVELIST_DEFAULT_FONT "Sans 8" static HKEY hkey; @@ -93,6 +95,28 @@ const char *subsurface_icon_name() return "subsurface.ico"; } +const char *subsurface_default_filename() +{ + if (default_filename) { + return default_filename; + } else { + char datapath[MAX_PATH]; + const char *user; + char *buffer; + int len; + + user = g_get_user_name(); + if (! SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, datapath))) { + datapath[0] = '.'; + datapath[1] = '\0'; + } + len = strlen(datapath) + strlen(user) + 17; + buffer = malloc(len); + snprintf(buffer, len, "%s\\Subsurface\\%s.xml", datapath, user); + return buffer; + } +} + void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar, GtkWidget *vbox, GtkUIManager *ui_manager) { -- cgit v1.2.3-70-g09d2 From 78c5aa9f071ab56e56bf760e3e7fc7f0f0d1b1ff Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 10 Sep 2012 12:27:00 -0700 Subject: Change behavior for the existing filename Previously we always picked the last file that was openend as the file name to save to. That seems counterintuitive when importing files or when opening multiple files. Especially if Subsurface was executed without a file on the command line and we are using the default file. Now we only remember a file name if it was the first one to ever be openend or if it was used in save-as. Signed-off-by: Dirk Hohndel --- dive.h | 2 +- gtk-gui.c | 10 +++++----- main.c | 2 +- parse-xml.c | 5 ++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/dive.h b/dive.h index 746b94093..af141bbde 100644 --- a/dive.h +++ b/dive.h @@ -379,7 +379,7 @@ static inline struct dive *get_dive(unsigned int nr) extern void parse_xml_init(void); extern void parse_xml_buffer(const char *url, const char *buf, int size, GError **error); -extern void set_filename(const char *filename); +extern void set_filename(const char *filename, gboolean force); extern void parse_file(const char *filename, GError **error); diff --git a/gtk-gui.c b/gtk-gui.c index 1d5fc4cc9..6666f5560 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -233,7 +233,7 @@ static void file_save_as(GtkWidget *w, gpointer data) if (filename){ save_dives(filename); - set_filename(filename); + set_filename(filename, TRUE); g_free(filename); mark_divelist_changed(FALSE); } @@ -1419,11 +1419,11 @@ void update_progressbar_text(progressbar_t *progress, const char *text) gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress->bar), text); } -void set_filename(const char *filename) +void set_filename(const char *filename, gboolean force) { - if (existing_filename) - free(existing_filename); - existing_filename = NULL; + if (!force && existing_filename) + return; + free(existing_filename); if (filename) existing_filename = strdup(filename); } diff --git a/main.c b/main.c index a2c24ec99..01306b1bf 100644 --- a/main.c +++ b/main.c @@ -243,7 +243,7 @@ int main(int argc, char **argv) parse_file(filename, &error); /* don't report errors - this file may not exist, but make sure we remember this as the filename in use */ - set_filename(filename); + set_filename(filename, FALSE); } report_dives(imported); diff --git a/parse-xml.c b/parse-xml.c index 1c4db7d9d..a4ae81b25 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1475,9 +1475,8 @@ void parse_xml_buffer(const char *url, const char *buffer, int size, GError **er } return; } - /* we assume that the last (or only) filename passed as argument is a - * great filename to use as default when saving the dives */ - set_filename(url); + /* remember, if necessary, that this is the filename to store to */ + set_filename(url, FALSE); reset_all(); dive_start(); #ifdef XSLT -- cgit v1.2.3-70-g09d2 From a8fd77865c3e3e0a547b8e06a047c44732fe92f2 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 10 Sep 2012 14:32:55 -0700 Subject: Implement Close menu option that allows closing the data file This requires some helper routines that allow us to clear out all the widgets. Signed-off-by: Dirk Hohndel --- dive.h | 2 ++ equipment.c | 6 ++++++ gtk-gui.c | 37 +++++++++++++++++++++++++++++++++++-- info.c | 11 +++++++++++ statistics.c | 29 +++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) diff --git a/dive.h b/dive.h index af141bbde..227de387c 100644 --- a/dive.h +++ b/dive.h @@ -390,8 +390,10 @@ extern xmlDoc *test_xslt_transforms(xmlDoc *doc); extern void show_dive_info(struct dive *); extern void show_dive_equipment(struct dive *, int w_idx); +extern void clear_equipment_widgets(void); extern void show_dive_stats(struct dive *); +extern void clear_stats_widgets(void); extern void update_dive(struct dive *new_dive); extern void save_dives(const char *filename); diff --git a/equipment.c b/equipment.c index d676fc05d..e81302c92 100644 --- a/equipment.c +++ b/equipment.c @@ -1612,3 +1612,9 @@ GtkWidget *equipment_widget(int w_idx) return vbox; } + +void clear_equipment_widgets() +{ + gtk_list_store_clear(cylinder_list[W_IDX_PRIMARY].model); + gtk_list_store_clear(weightsystem_list[W_IDX_PRIMARY].model); +} diff --git a/gtk-gui.c b/gtk-gui.c index 6666f5560..a6a124fde 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -277,11 +277,11 @@ static gboolean ask_save_changes() if (!existing_filename){ label = gtk_label_new ( - "You have unsaved changes\nWould you like to save those before exiting the program?"); + "You have unsaved changes\nWould you like to save those before closing the datafile?"); } else { char *label_text = (char*) malloc(sizeof(char) * (93 + strlen(existing_filename))); sprintf(label_text, - "You have unsaved changes to file: %s \nWould you like to save those before exiting the program?", + "You have unsaved changes to file: %s \nWould you like to save those before closing the datafile?", existing_filename); label = gtk_label_new (label_text); g_free(label_text); @@ -299,6 +299,37 @@ static gboolean ask_save_changes() return quit; } +static void file_close(GtkWidget *w, gpointer data) +{ + int i; + + if (unsaved_changes()) + if (ask_save_changes() == FALSE) + return; + existing_filename = NULL; + + /* free the dives and trips */ + for (i = 0; i < dive_table.nr; i++) + free(get_dive(i)); + dive_table.nr = 0; + dive_table.preexisting = 0; + g_list_free_full(dive_trip_list, free); + dive_trip_list = NULL; + + /* clear the selection and the statistics */ + amount_selected = 0; + selected_dive = 0; + process_selected_dives(); + clear_stats_widgets(); + + /* clear the equipment page */ + clear_equipment_widgets(); + + /* redraw the screen */ + dive_list_update_dives(); + show_dive_info(NULL); +} + static gboolean on_delete(GtkWidget* w, gpointer data) { /* Make sure to flush any modified dive data */ @@ -842,6 +873,7 @@ static GtkActionEntry menu_items[] = { { "OpenFile", GTK_STOCK_OPEN, NULL, CTRLCHAR "O", NULL, G_CALLBACK(file_open) }, { "SaveFile", GTK_STOCK_SAVE, NULL, CTRLCHAR "S", NULL, G_CALLBACK(file_save) }, { "SaveAsFile", GTK_STOCK_SAVE_AS, NULL, SHIFTCHAR CTRLCHAR "S", NULL, G_CALLBACK(file_save_as) }, + { "CloseFile", GTK_STOCK_CLOSE, NULL, NULL, NULL, G_CALLBACK(file_close) }, { "Print", GTK_STOCK_PRINT, NULL, CTRLCHAR "P", NULL, G_CALLBACK(do_print) }, { "Import", NULL, "Import", NULL, NULL, G_CALLBACK(import_dialog) }, { "AddDive", GTK_STOCK_ADD, "Add Dive", NULL, NULL, G_CALLBACK(add_dive_cb) }, @@ -870,6 +902,7 @@ static const gchar* ui_string = " \ \ \ \ + \ \ \ \ diff --git a/info.c b/info.c index 3efb40cf8..34ddfa923 100644 --- a/info.c +++ b/info.c @@ -113,6 +113,17 @@ void show_dive_info(struct dive *dive) const char *text; char buffer[80]; + if (!dive) { + gtk_window_set_title(GTK_WINDOW(main_window), "Subsurface"); + SET_TEXT_VALUE(divemaster); + SET_TEXT_VALUE(buddy); + SET_TEXT_VALUE(location); + SET_TEXT_VALUE(suit); + gtk_entry_set_text(rating, star_strings[0]); + gtk_text_buffer_set_text(gtk_text_view_get_buffer(notes), "", -1); + return; + } + /* dive number and location (or lacking that, the date) go in the window title */ text = dive->location; if (!text) diff --git a/statistics.c b/statistics.c index a53617337..674efbb94 100644 --- a/statistics.c +++ b/statistics.c @@ -416,3 +416,32 @@ GtkWidget *single_stats_widget(void) return vbox; } + +void clear_stats_widgets(void) +{ + set_label(single_w.date, ""); + set_label(single_w.dive_time, ""); + set_label(single_w.surf_intv, ""); + set_label(single_w.max_depth, ""); + set_label(single_w.avg_depth, ""); + set_label(single_w.water_temp, ""); + set_label(single_w.sac, ""); + set_label(single_w.sac, ""); + set_label(single_w.otu, ""); + set_label(single_w.o2he, ""); + set_label(single_w.gas_used, ""); + set_label(stats_w.total_time,""); + set_label(stats_w.avg_time,""); + set_label(stats_w.shortest_time,""); + set_label(stats_w.longest_time,""); + set_label(stats_w.max_overall_depth,""); + set_label(stats_w.min_overall_depth,""); + set_label(stats_w.avg_overall_depth,""); + set_label(stats_w.min_sac,""); + set_label(stats_w.avg_sac,""); + set_label(stats_w.max_sac,""); + set_label(stats_w.selection_size,""); + set_label(stats_w.max_temp,""); + set_label(stats_w.avg_temp,""); + set_label(stats_w.min_temp,""); +} -- cgit v1.2.3-70-g09d2 From 3b907d8479fcee553d3601da62ecae1d90d201f8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 10 Sep 2012 14:39:07 -0700 Subject: Fix silly folder permission bug I forgot to give the user execute permission on the folder that subsurface might create to store the datafile in. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index a6a124fde..404530024 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -255,7 +255,7 @@ static void file_save(GtkWidget *w, gpointer data) current_def_dir = path_and_file(existing_filename, ¤t_def_file); if (stat(current_def_dir, &sb) != 0) { - mkdir(current_def_dir, S_IRUSR | S_IWUSR); + mkdir(current_def_dir, S_IRWXU); } } free((void *)current_default); @@ -507,7 +507,7 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) * For gtk's file select box to make sense we create it if needed and then remove * it after the dialog has run */ if (stat(current_def_dir, &sb) != 0) { - if (mkdir(current_def_dir, S_IRUSR | S_IWUSR) == 0) + if (mkdir(current_def_dir, S_IRWXU) == 0) need_rmdir = TRUE; } gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs_dialog), current_def_dir); -- cgit v1.2.3-70-g09d2 From b4d55c8b598b648acda0f8107868b8753283c72e Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 10 Sep 2012 14:44:48 -0700 Subject: Change the definition of "dive table changed" We only ask to save changes if the dive table was changed. Yet we didn't consider the dive table changed if it was initially empty. So starting with an empty file and making changes we were quitting without saving. Signed-off-by: Dirk Hohndel --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 01306b1bf..46e22041d 100644 --- a/main.c +++ b/main.c @@ -140,8 +140,8 @@ void report_dives(gboolean is_imported) if (last && last->number) try_to_renumber(last, preexisting); - /* did we have dives in the table and added more? */ - if (last && preexisting != dive_table.nr) + /* did we add dives to the dive table? */ + if (preexisting != dive_table.nr) mark_divelist_changed(TRUE); } dive_table.preexisting = dive_table.nr; -- cgit v1.2.3-70-g09d2 From 2a9679dac62d16ad727dc111f02bf441a2d6c7e1 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Tue, 11 Sep 2012 11:42:47 -0700 Subject: Use glibio functions for mkdir Suggested-by: Jef Driesen Signed-off-by: Dirk Hohndel --- dive.h | 1 + gtk-gui.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dive.h b/dive.h index 227de387c..ca90a9ae4 100644 --- a/dive.h +++ b/dive.h @@ -5,6 +5,7 @@ #include #include +#include #include /* diff --git a/gtk-gui.c b/gtk-gui.c index 404530024..d24675927 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -255,7 +255,7 @@ static void file_save(GtkWidget *w, gpointer data) current_def_dir = path_and_file(existing_filename, ¤t_def_file); if (stat(current_def_dir, &sb) != 0) { - mkdir(current_def_dir, S_IRWXU); + g_mkdir(current_def_dir, S_IRWXU); } } free((void *)current_default); @@ -507,7 +507,7 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) * For gtk's file select box to make sense we create it if needed and then remove * it after the dialog has run */ if (stat(current_def_dir, &sb) != 0) { - if (mkdir(current_def_dir, S_IRWXU) == 0) + if (g_mkdir(current_def_dir, S_IRWXU) == 0) need_rmdir = TRUE; } gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs_dialog), current_def_dir); -- cgit v1.2.3-70-g09d2 From be941e00b20cc0b8b3b46e04200ce15c3023ad23 Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Tue, 11 Sep 2012 02:07:42 +0300 Subject: Inline g_list_free_full for better compatibility Replaced g_list_free_full with the inlined alternave: g_list_foreach(dive_trip_list, (GFunc)free, NULL); g_list_free(dive_trip_list); once again my version on debian 6.0.x has libraries up-to-date yet outdated. i guess i have to suggest against API which has the "Since " text and is fairly recent on documentation webpages. Signed-off-by: "Lubomir I. Ivanov" I took only one hunk from the patch that Lubomir sent - the rest I implemented differently in the previous commit. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gtk-gui.c b/gtk-gui.c index d24675927..e520d9b75 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -313,7 +313,11 @@ static void file_close(GtkWidget *w, gpointer data) free(get_dive(i)); dive_table.nr = 0; dive_table.preexisting = 0; - g_list_free_full(dive_trip_list, free); + + /* inlined version of g_list_free_full(dive_trip_list, free); */ + g_list_foreach(dive_trip_list, (GFunc)free, NULL); + g_list_free(dive_trip_list); + dive_trip_list = NULL; /* clear the selection and the statistics */ -- cgit v1.2.3-70-g09d2 From 1afe36840ddbc2d139c1f7e2b3607aecc88d9890 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Tue, 11 Sep 2012 20:52:54 -0700 Subject: Fix memory handling error on MacOS We are not allowed to free a string that we get back from the config APIs. So strdup it instead to be compatible with Linux in that respect. Signed-off-by: Dirk Hohndel --- macos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macos.c b/macos.c index fbf399890..f2e58338e 100644 --- a/macos.c +++ b/macos.c @@ -54,7 +54,7 @@ const void *subsurface_get_conf(char *name, pref_type_t type) strpref = CFPreferencesCopyAppValue(CFSTR_VAR(name), SUBSURFACE_PREFERENCES); if (!strpref) return NULL; - return CFStringGetCStringPtr(strpref, kCFStringEncodingMacRoman); + return strdup(CFStringGetCStringPtr(strpref, kCFStringEncodingMacRoman)); } /* we shouldn't get here, but having this line makes the compiler happy */ return NULL; -- cgit v1.2.3-70-g09d2 From 1ae4b80027a97e8fbe553b980dc17ea540000d88 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 12 Sep 2012 09:18:56 -0700 Subject: Make sure Subsurface receives Quit / Command-Q callback on Mac As usual, things work slightly different on Mac. Quartz delivers some (but not all) accelerator notifications differently. Command-Q and Subsurface->Quit now work on Mac as well. Signed-off-by: Dirk Hohndel --- display-gtk.h | 1 + gtk-gui.c | 2 +- macos.c | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/display-gtk.h b/display-gtk.h index e03861d39..9d0ea4ed3 100644 --- a/display-gtk.h +++ b/display-gtk.h @@ -49,6 +49,7 @@ extern const char *subsurface_USB_name(void); extern const char *subsurface_icon_name(void); extern void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar, GtkWidget *vbox, GtkUIManager *ui_manager); +extern void quit(GtkWidget *w, gpointer data); extern visible_cols_t visible_cols; diff --git a/gtk-gui.c b/gtk-gui.c index e520d9b75..cd7ebe5cc 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -355,7 +355,7 @@ static void on_destroy(GtkWidget* w, gpointer data) gtk_main_quit(); } -static void quit(GtkWidget *w, gpointer data) +void quit(GtkWidget *w, gpointer data) { /* Make sure to flush any modified dive data */ update_dive(NULL); diff --git a/macos.c b/macos.c index f2e58338e..d37b0a925 100644 --- a/macos.c +++ b/macos.c @@ -104,6 +104,12 @@ const char *subsurface_default_filename() } } +static void show_main_window(GtkWidget *w, gpointer data) +{ + gtk_widget_show(main_window); + gtk_window_present(GTK_WINDOW(main_window)); +} + void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar, GtkWidget *vbox, GtkUIManager *ui_manager) { @@ -141,5 +147,8 @@ void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar, gtk_osxapplication_insert_app_menu_item (osx_app, sep, 3); gtk_osxapplication_set_use_quartz_accelerators(osx_app, TRUE); + g_signal_connect(osx_app,"NSApplicationDidBecomeActive",G_CALLBACK(show_main_window),NULL); + g_signal_connect(osx_app,"NSApplicationWillTerminate",G_CALLBACK(quit),NULL); + gtk_osxapplication_ready(osx_app); } -- cgit v1.2.3-70-g09d2 From 5dbf10a6d679e38b3e0a407bb6659f9bb4b8a6ce Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Wed, 12 Sep 2012 23:40:22 +0300 Subject: various small fixes to the defaultfile model 1) For safety reasons we no longer remove the default directory after creating it. This prevents an access error (on windows) and also a couple of small exploits that could have been possible, resulting in undefined behaviour. 2) Once "default_filename" is allocated keep it until the value has to change. The value is finaly released once the program is ready to close. 3) When picking a new default file, grab the new string directly from the GSList. 4) When storing the new default file from the preferences dialog, make sure we also update "existing_filename" if needed. Signed-off-by: Lubomir I. Ivanov Fixed some whitespace issues, made commit message and one of the comments in the code somewhat clearer. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index cd7ebe5cc..bfb40a7bc 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -258,7 +258,6 @@ static void file_save(GtkWidget *w, gpointer data) g_mkdir(current_def_dir, S_IRWXU); } } - free((void *)current_default); save_dives(existing_filename); mark_divelist_changed(FALSE); } @@ -492,11 +491,10 @@ static void event_toggle(GtkWidget *w, gpointer _data) static void pick_default_file(GtkWidget *w, GtkButton *button) { GtkWidget *fs_dialog; - const char *current_default, *new_default = NULL; + const char *current_default; char *current_def_file, *current_def_dir; GtkFileFilter *filter; struct stat sb; - gboolean need_rmdir = FALSE; fs_dialog = gtk_file_chooser_dialog_new("Choose Default XML File", GTK_WINDOW(main_window), @@ -506,14 +504,12 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) NULL); current_default = subsurface_default_filename(); current_def_dir = path_and_file(current_default, ¤t_def_file); - free((void *)current_default); + /* it's possible that the directory doesn't exist (especially for the default) - * For gtk's file select box to make sense we create it if needed and then remove - * it after the dialog has run */ - if (stat(current_def_dir, &sb) != 0) { - if (g_mkdir(current_def_dir, S_IRWXU) == 0) - need_rmdir = TRUE; - } + * For gtk's file select box to make sense we create it */ + if (stat(current_def_dir, &sb) != 0) + g_mkdir(current_def_dir, S_IRWXU); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs_dialog), current_def_dir); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fs_dialog), current_def_file); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fs_dialog), FALSE); @@ -530,15 +526,11 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) GSList *list; list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(fs_dialog)); - if (g_slist_length(list) == 1) { - new_default = strdup(list->data); - } + if (g_slist_length(list) == 1) + gtk_button_set_label(button, list->data); g_slist_free(list); - if (new_default) - gtk_button_set_label(button, new_default); } - if (need_rmdir) - rmdir(current_def_dir); + free(current_def_dir); free(current_def_file); gtk_widget_destroy(fs_dialog); @@ -687,6 +679,12 @@ static void preferences_dialog(GtkWidget *w, gpointer data) subsurface_set_conf("divelist_font", PREF_STRING, divelist_font); subsurface_set_conf("autogroup", PREF_BOOL, BOOL_TO_PTR(autogroup)); new_default = strdup(gtk_button_get_label(GTK_BUTTON(button))); + + /* if we opened the default file and are changing its name, + * update existing_filename */ + if (strcmp(current_default, existing_filename) == 0) + existing_filename = (char *)new_default; + if (strcmp(current_default, new_default)) { subsurface_set_conf("default_filename", PREF_STRING, new_default); free((void *)default_filename); @@ -697,7 +695,6 @@ static void preferences_dialog(GtkWidget *w, gpointer data) subsurface_flush_conf(); } gtk_widget_destroy(dialog); - free((void *)current_default); } static void create_toggle(const char* label, int *on, void *_data) @@ -1092,6 +1089,8 @@ void run_ui(void) void exit_ui(void) { subsurface_close_conf(); + if (default_filename) + free((char *)default_filename); } typedef struct { -- cgit v1.2.3-70-g09d2 From c74f58786d0a031a184b0933ddd19f7c48031bcc Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 13 Sep 2012 10:46:09 -0700 Subject: Fix memory leaks and one potential NULL dereference Always make sure to clear the memory allocated at the "existing_filename" pointer when setting it to a new address or NULL. Signed-off-by: Lubomir I. Ivanov Lifted these changes from a larger commit. The other changes I'll reimplement in the next commit. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index bfb40a7bc..5c8d960b2 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -305,6 +305,9 @@ static void file_close(GtkWidget *w, gpointer data) if (unsaved_changes()) if (ask_save_changes() == FALSE) return; + + if (existing_filename) + free(existing_filename); existing_filename = NULL; /* free the dives and trips */ @@ -682,8 +685,12 @@ static void preferences_dialog(GtkWidget *w, gpointer data) /* if we opened the default file and are changing its name, * update existing_filename */ - if (strcmp(current_default, existing_filename) == 0) - existing_filename = (char *)new_default; + if (existing_filename) { + if (strcmp(current_default, existing_filename) == 0) { + free(existing_filename); + existing_filename = strdup(new_default); + } + } if (strcmp(current_default, new_default)) { subsurface_set_conf("default_filename", PREF_STRING, new_default); @@ -1091,6 +1098,8 @@ void exit_ui(void) subsurface_close_conf(); if (default_filename) free((char *)default_filename); + if (existing_filename) + free(existing_filename); } typedef struct { -- cgit v1.2.3-70-g09d2 From 3d4be85f3521869f2703d9efb6b25c78ef90adea Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 13 Sep 2012 10:53:30 -0700 Subject: Prevent the preferences dialog from getting focus with file selector open The idea is based on Lubomir's code but the implementation is radically different. Instead of having the preferences dialog be referenced by a global variable we simply look up the appropriate ancestor of the current widget. Inspired-by: "Lubomir I. Ivanov" Signed-off-by: Dirk Hohndel --- gtk-gui.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gtk-gui.c b/gtk-gui.c index 5c8d960b2..d41ea07d6 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -493,7 +493,7 @@ static void event_toggle(GtkWidget *w, gpointer _data) static void pick_default_file(GtkWidget *w, GtkButton *button) { - GtkWidget *fs_dialog; + GtkWidget *fs_dialog, *preferences; const char *current_default; char *current_def_file, *current_def_dir; GtkFileFilter *filter; @@ -505,6 +505,9 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); + preferences = gtk_widget_get_ancestor(w, GTK_TYPE_DIALOG); + gtk_window_set_accept_focus(GTK_WINDOW(preferences), FALSE); + current_default = subsurface_default_filename(); current_def_dir = path_and_file(current_default, ¤t_def_file); @@ -537,6 +540,7 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) free(current_def_dir); free(current_def_file); gtk_widget_destroy(fs_dialog); + gtk_window_set_accept_focus(GTK_WINDOW(preferences), TRUE); } static void preferences_dialog(GtkWidget *w, gpointer data) -- cgit v1.2.3-70-g09d2 From 9f5d9bd94f092739f0f8e846f8e19ec30a8c0c52 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 13 Sep 2012 11:17:38 -0700 Subject: Use glib file and pathname functions My silly reimplementation of these functions was broken on Windows, anyway. This is much cleaner. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 41 +++++++---------------------------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index d41ea07d6..d2e2817d8 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -174,36 +174,6 @@ static void file_open(GtkWidget *w, gpointer data) gtk_widget_destroy(dialog); } -/* return the path and the file component contained in the full path */ -static char *path_and_file(const char *pathin, char **fileout) { - const char *slash = pathin, *next; - char *result; - size_t len, n; - - if (! pathin) { - *fileout = strdup(""); - return strdup(""); - } - while ((next = strpbrk(slash + 1, "\\/"))) - slash = next; - if (pathin != slash) - slash++; - *fileout = strdup(slash); - - /* strndup(pathin, slash - pathin) */ - n = slash - pathin; - len = strlen(pathin); - if (n < len) - len = n; - - result = (char *)malloc(len + 1); - if (!result) - return 0; - - result[len] = '\0'; - return (char *)memcpy(result, pathin, len); -} - static void file_save_as(GtkWidget *w, gpointer data) { GtkWidget *dialog; @@ -219,7 +189,8 @@ static void file_save_as(GtkWidget *w, gpointer data) NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); - current_dir = path_and_file(existing_filename, ¤t_file); + current_dir = g_path_get_dirname(existing_filename); + current_file = g_path_get_basename(existing_filename); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), current_dir); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), current_file); @@ -250,13 +221,14 @@ static void file_save(GtkWidget *w, gpointer data) if (strcmp(existing_filename, current_default) == 0) { /* if we are using the default filename the directory * that we are creating the file in may not exist */ - char *current_def_dir, *current_def_file; + char *current_def_dir; struct stat sb; - current_def_dir = path_and_file(existing_filename, ¤t_def_file); + current_def_dir = g_path_get_dirname(existing_filename); if (stat(current_def_dir, &sb) != 0) { g_mkdir(current_def_dir, S_IRWXU); } + free(current_def_dir); } save_dives(existing_filename); mark_divelist_changed(FALSE); @@ -509,7 +481,8 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) gtk_window_set_accept_focus(GTK_WINDOW(preferences), FALSE); current_default = subsurface_default_filename(); - current_def_dir = path_and_file(current_default, ¤t_def_file); + current_def_dir = g_path_get_dirname(current_default); + current_def_file = g_path_get_basename(current_default); /* it's possible that the directory doesn't exist (especially for the default) * For gtk's file select box to make sense we create it */ -- cgit v1.2.3-70-g09d2 From 1771500078312047d4c9ca1800af17029983e69f Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 04:44:00 -0700 Subject: Don't show an error if we can't load the default file The user may not have created it, yet. Signed-off-by: Dirk Hohndel --- file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/file.c b/file.c index b9a598e2a..ca39c8dd6 100644 --- a/file.c +++ b/file.c @@ -253,6 +253,10 @@ void parse_file(const char *filename, GError **error) struct memblock mem; if (readfile(filename, &mem) < 0) { + /* we don't want to display an error if this was the default file */ + if (default_filename && ! strcmp(filename, default_filename)) + return; + fprintf(stderr, "Failed to read '%s'.\n", filename); if (error) { *error = g_error_new(g_quark_from_string("subsurface"), -- cgit v1.2.3-70-g09d2 From 65d9d488452c6d13d8db7812dfd09be0e985876d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 05:29:12 -0700 Subject: Display current filename in windows title This seems to make sense since we have a pretty strong concept of the "active file" that we are working on. Signed-off-by: Dirk Hohndel --- dive.h | 1 + gtk-gui.c | 3 +-- info.c | 16 ++++++++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dive.h b/dive.h index ca90a9ae4..85d4b9fa4 100644 --- a/dive.h +++ b/dive.h @@ -463,6 +463,7 @@ const char *monthname(int mon); extern const char *star_strings[]; extern const char *default_filename; +extern char *existing_filename; extern const char *subsurface_default_filename(void); #define AIR_PERMILLE 209 diff --git a/gtk-gui.c b/gtk-gui.c index d2e2817d8..e5bdac9f2 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -25,7 +25,7 @@ GtkWidget *vpane, *hpane; GtkWidget *notebook; int error_count; - +char *existing_filename; const char *divelist_font; const char *default_filename; @@ -81,7 +81,6 @@ void repaint_dive(void) gtk_widget_queue_draw(dive_profile); } -static char *existing_filename; static gboolean need_icon = TRUE; static void on_info_bar_response(GtkWidget *widget, gint response, diff --git a/info.c b/info.c index 34ddfa923..a4d4d4179 100644 --- a/info.c +++ b/info.c @@ -112,9 +112,15 @@ void show_dive_info(struct dive *dive) { const char *text; char buffer[80]; + char title[80]; if (!dive) { - gtk_window_set_title(GTK_WINDOW(main_window), "Subsurface"); + if (existing_filename) { + snprintf(title, 80, "Subsurface: %s", g_path_get_basename(existing_filename)); + gtk_window_set_title(GTK_WINDOW(main_window), title); + } else { + gtk_window_set_title(GTK_WINDOW(main_window), "Subsurface"); + } SET_TEXT_VALUE(divemaster); SET_TEXT_VALUE(buddy); SET_TEXT_VALUE(location); @@ -136,8 +142,14 @@ void show_dive_info(struct dive *dive) text = buffer; if (!dive->number) text += 10; /* Skip the "Dive #0 - " part */ - gtk_window_set_title(GTK_WINDOW(main_window), text); + /* put it all together */ + if (existing_filename) { + snprintf(title, 80, "%s: %s", g_path_get_basename(existing_filename), text); + gtk_window_set_title(GTK_WINDOW(main_window), title); + } else { + gtk_window_set_title(GTK_WINDOW(main_window), text); + } SET_TEXT_VALUE(divemaster); SET_TEXT_VALUE(buddy); SET_TEXT_VALUE(location); -- cgit v1.2.3-70-g09d2 From d3bf8af7fe2d862b2b4188332776f86cde00cbe6 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 05:33:25 -0700 Subject: File Open now closes the previous file, first This is a pretty significant semantic change - Open used to act more like Import; you added more dives to the divelist. With this change it instead acts more like the traditional File->Open in that it closes the previous file, first. The diff hides the minimalistic nature of the change - it seemed cleaner to move the file_open function around than to do a forward declaration of file_close. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 97 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index e5bdac9f2..5153ab21d 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -126,53 +126,6 @@ void report_error(GError* error) } } -static void file_open(GtkWidget *w, gpointer data) -{ - GtkWidget *dialog; - GtkFileFilter *filter; - - dialog = gtk_file_chooser_dialog_new("Open File", - GTK_WINDOW(main_window), - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); - - filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filter, "*.xml"); - gtk_file_filter_add_pattern(filter, "*.XML"); - gtk_file_filter_add_pattern(filter, "*.sda"); - gtk_file_filter_add_pattern(filter, "*.SDA"); - gtk_file_filter_add_mime_type(filter, "text/xml"); - gtk_file_filter_set_name(filter, "XML file"); - gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); - - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - GSList *filenames, *fn_glist; - char *filename; - filenames = fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - - GError *error = NULL; - while(filenames != NULL) { - filename = filenames->data; - parse_file(filename, &error); - if (error != NULL) - { - report_error(error); - g_error_free(error); - error = NULL; - } - - g_free(filename); - filenames = g_slist_next(filenames); - } - g_slist_free(fn_glist); - report_dives(FALSE); - } - gtk_widget_destroy(dialog); -} - static void file_save_as(GtkWidget *w, gpointer data) { GtkWidget *dialog; @@ -307,6 +260,56 @@ static void file_close(GtkWidget *w, gpointer data) show_dive_info(NULL); } +static void file_open(GtkWidget *w, gpointer data) +{ + GtkWidget *dialog; + GtkFileFilter *filter; + + /* first, close the existing file, if any */ + file_close(w, data); + + dialog = gtk_file_chooser_dialog_new("Open File", + GTK_WINDOW(main_window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); + + filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filter, "*.xml"); + gtk_file_filter_add_pattern(filter, "*.XML"); + gtk_file_filter_add_pattern(filter, "*.sda"); + gtk_file_filter_add_pattern(filter, "*.SDA"); + gtk_file_filter_add_mime_type(filter, "text/xml"); + gtk_file_filter_set_name(filter, "XML file"); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + GSList *filenames, *fn_glist; + char *filename; + filenames = fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + + GError *error = NULL; + while(filenames != NULL) { + filename = filenames->data; + parse_file(filename, &error); + if (error != NULL) + { + report_error(error); + g_error_free(error); + error = NULL; + } + + g_free(filename); + filenames = g_slist_next(filenames); + } + g_slist_free(fn_glist); + report_dives(FALSE); + } + gtk_widget_destroy(dialog); +} + static gboolean on_delete(GtkWidget* w, gpointer data) { /* Make sure to flush any modified dive data */ -- cgit v1.2.3-70-g09d2 From b2727ecfda729164a3d18c73787ccc67bd94c1aa Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 11:41:38 -0700 Subject: Move Import menu entry back to File menu This should make things more consistent, especially now that "Open" actually does just that and no longer behaves almost like "Import". The downside is that the import from a dive computer is now in the File menu as well and no longer in the Log menu, where Linus originally had moved it to in commit 3cace090989b. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index 5153ab21d..2ad2cb60e 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -862,7 +862,7 @@ static GtkActionEntry menu_items[] = { { "SaveAsFile", GTK_STOCK_SAVE_AS, NULL, SHIFTCHAR CTRLCHAR "S", NULL, G_CALLBACK(file_save_as) }, { "CloseFile", GTK_STOCK_CLOSE, NULL, NULL, NULL, G_CALLBACK(file_close) }, { "Print", GTK_STOCK_PRINT, NULL, CTRLCHAR "P", NULL, G_CALLBACK(do_print) }, - { "Import", NULL, "Import", NULL, NULL, G_CALLBACK(import_dialog) }, + { "Import", NULL, "Import", SHIFTCHAR CTRLCHAR "O", NULL, G_CALLBACK(import_dialog) }, { "AddDive", GTK_STOCK_ADD, "Add Dive", NULL, NULL, G_CALLBACK(add_dive_cb) }, { "Preferences", GTK_STOCK_PREFERENCES, "Preferences", PREFERENCE_ACCEL, NULL, G_CALLBACK(preferences_dialog) }, { "Renumber", NULL, "Renumber", NULL, NULL, G_CALLBACK(renumber_dialog) }, @@ -887,6 +887,7 @@ static const gchar* ui_string = " \ \ \ \ + \ \ \ \ @@ -897,7 +898,6 @@ static const gchar* ui_string = " \ \ \ \ - \ \ \ \ -- cgit v1.2.3-70-g09d2 From dea8d47b695b0095d3820e68be01dd45f19b547c Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 14:24:34 -0700 Subject: The Open menu entry should open just one file The single file that is our new data file (and the file that we'll change if it was modified). Signed-off-by: Dirk Hohndel --- gtk-gui.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gtk-gui.c b/gtk-gui.c index 2ad2cb60e..85366621f 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -274,7 +274,8 @@ static void file_open(GtkWidget *w, gpointer data) GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); + /* when opening the data file we should allow only one file to be chosen */ + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter, "*.xml"); -- cgit v1.2.3-70-g09d2 From ca696dd0cd7da7af7893639f5786e56972cbef09 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 15:12:30 -0700 Subject: Reimplement the GtkFileChooserButton for import One of the limitations of GtkFileChooserButton is that it only allows one file to be chosen (so that it can display that file name in the button after the file chooser dialog finishes). Since in the import dialog we never want to show the button with the filename(s) filled in but want to directly execute the import once files have been selected, I reimplemented the button to simply open a multi file chooser when clicked and to then run the import function if one or more file names were selected. This does appear to require some more code but gets us a much more useful and consistent implementation. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 85 +++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 30 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index 85366621f..355598983 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -1276,32 +1276,40 @@ static GtkEntry *dive_computer_device(GtkWidget *vbox) return GTK_ENTRY(entry); } -/* once a file is selected in the FileChooserButton we want to exit the import dialog */ -static void on_file_set(GtkFileChooserButton *widget, gpointer _data) +static void pick_import_files(GtkWidget *w, GSList **filelist) { - GtkDialog *main_dialog = _data; - - gtk_dialog_response(main_dialog, GTK_RESPONSE_ACCEPT); -} - -static GtkWidget *xml_file_selector(GtkWidget *vbox, GtkWidget *main_dialog) -{ - GtkWidget *hbox, *frame, *chooser, *dialog; + GtkWidget *fs_dialog, *import; + const char *current_default; + char *current_def_dir; GtkFileFilter *filter; + struct stat sb; - hbox = gtk_hbox_new(FALSE, 6); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3); - - frame = gtk_frame_new("XML file name"); - gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, TRUE, 3); - dialog = gtk_file_chooser_dialog_new("Open XML File", + *filelist = NULL; + fs_dialog = gtk_file_chooser_dialog_new("Choose Files to import", GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); + import = gtk_widget_get_ancestor(w, GTK_TYPE_DIALOG); + gtk_window_set_accept_focus(GTK_WINDOW(import), FALSE); + + /* I'm not sure what the best default path should be... */ + if (existing_filename) { + current_def_dir = g_path_get_dirname(existing_filename); + } else { + current_default = subsurface_default_filename(); + current_def_dir = g_path_get_dirname(current_default); + free((void *)current_default); + } + + /* it's possible that the directory doesn't exist (especially for the default) + * For gtk's file select box to make sense we create it */ + if (stat(current_def_dir, &sb) != 0) + g_mkdir(current_def_dir, S_IRWXU); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs_dialog), current_def_dir); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fs_dialog), TRUE); filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter, "*.xml"); gtk_file_filter_add_pattern(filter, "*.XML"); @@ -1309,15 +1317,33 @@ static GtkWidget *xml_file_selector(GtkWidget *vbox, GtkWidget *main_dialog) gtk_file_filter_add_pattern(filter, "*.SDA"); gtk_file_filter_add_mime_type(filter, "text/xml"); gtk_file_filter_set_name(filter, "XML file"); - gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fs_dialog), filter); + gtk_widget_show_all(fs_dialog); + if (gtk_dialog_run(GTK_DIALOG(fs_dialog)) == GTK_RESPONSE_ACCEPT) + *filelist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(fs_dialog)); + free(current_def_dir); + gtk_widget_destroy(fs_dialog); + gtk_window_set_accept_focus(GTK_WINDOW(import), TRUE); + /* if we selected one or more files, pretent that we clicked OK in the import dialog */ + if (*filelist != NULL) + gtk_dialog_response(GTK_DIALOG(import), GTK_RESPONSE_ACCEPT); +} - chooser = gtk_file_chooser_button_new_with_dialog(dialog); - g_signal_connect(G_OBJECT(chooser), "file-set", G_CALLBACK(on_file_set), main_dialog); +static void xml_file_selector(GtkWidget *vbox, GtkWidget *main_dialog, GSList **list) +{ + GtkWidget *hbox, *frame, *chooser, *box; - gtk_file_chooser_button_set_width_chars(GTK_FILE_CHOOSER_BUTTON(chooser), 30); - gtk_container_add(GTK_CONTAINER(frame), chooser); + hbox = gtk_hbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3); + + frame = gtk_frame_new("XML file name"); + gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, TRUE, 3); - return chooser; + box = gtk_hbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER(frame), box); + chooser = gtk_button_new_with_label("Pick XML file to import"); + g_signal_connect(G_OBJECT(chooser), "clicked", G_CALLBACK(pick_import_files), list); + gtk_box_pack_start(GTK_BOX(box), chooser, FALSE, FALSE, 6); } static void do_import_file(gpointer data, gpointer user_data) @@ -1360,9 +1386,9 @@ void import_dialog(GtkWidget *w, gpointer data) { int result; GtkWidget *dialog, *hbox, *vbox, *label, *info = NULL; + GSList *filenames; GtkComboBox *computer; GtkEntry *device; - GtkWidget *XMLchooser; device_data_t devicedata = { .devname = NULL, }; @@ -1377,7 +1403,7 @@ void import_dialog(GtkWidget *w, gpointer data) vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); label = gtk_label_new("Import: \nLoad XML file or import directly from dive computer"); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 3); - XMLchooser = xml_file_selector(vbox, dialog); + xml_file_selector(vbox, dialog, &filenames); computer = dive_computer_selector(vbox); device = dive_computer_device(vbox); hbox = gtk_hbox_new(FALSE, 6); @@ -1392,14 +1418,13 @@ repeat: dc_descriptor_t *descriptor; GtkTreeIter iter; GtkTreeModel *model; - GSList *list; + case GTK_RESPONSE_ACCEPT: /* what happened - did the user pick a file? In that case * we ignore whether a dive computer model was picked */ if (info) gtk_widget_destroy(info); - list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(XMLchooser)); - if (g_slist_length(list) == 0) { + if (g_slist_length(filenames) == 0) { const char *vendor, *product; if (!gtk_combo_box_get_active_iter(computer, &iter)) @@ -1422,8 +1447,8 @@ repeat: if (info) goto repeat; } else { - g_slist_foreach(list,do_import_file,NULL); - g_slist_free(list); + g_slist_foreach(filenames,do_import_file,NULL); + g_slist_free(filenames); } break; default: -- cgit v1.2.3-70-g09d2 From eddea0e5e3f8cdf29cd71e1b90c22ec0f511697c Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 15:22:36 -0700 Subject: Put creation of the file selector box filter into helper function This avoids duplication of code. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index 355598983..3833b5892 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -126,6 +126,19 @@ void report_error(GError* error) } } +static GtkFileFilter *setup_filter(void) +{ + GtkFileFilter *filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filter, "*.xml"); + gtk_file_filter_add_pattern(filter, "*.XML"); + gtk_file_filter_add_pattern(filter, "*.sda"); + gtk_file_filter_add_pattern(filter, "*.SDA"); + gtk_file_filter_add_mime_type(filter, "text/xml"); + gtk_file_filter_set_name(filter, "XML file"); + + return filter; +} + static void file_save_as(GtkWidget *w, gpointer data) { GtkWidget *dialog; @@ -277,13 +290,7 @@ static void file_open(GtkWidget *w, gpointer data) /* when opening the data file we should allow only one file to be chosen */ gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); - filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filter, "*.xml"); - gtk_file_filter_add_pattern(filter, "*.XML"); - gtk_file_filter_add_pattern(filter, "*.sda"); - gtk_file_filter_add_pattern(filter, "*.SDA"); - gtk_file_filter_add_mime_type(filter, "text/xml"); - gtk_file_filter_set_name(filter, "XML file"); + filter = setup_filter(); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { @@ -495,13 +502,7 @@ static void pick_default_file(GtkWidget *w, GtkButton *button) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs_dialog), current_def_dir); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fs_dialog), current_def_file); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fs_dialog), FALSE); - filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filter, "*.xml"); - gtk_file_filter_add_pattern(filter, "*.XML"); - gtk_file_filter_add_pattern(filter, "*.sda"); - gtk_file_filter_add_pattern(filter, "*.SDA"); - gtk_file_filter_add_mime_type(filter, "text/xml"); - gtk_file_filter_set_name(filter, "XML file"); + filter = setup_filter(); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fs_dialog), filter); gtk_widget_show_all(fs_dialog); if (gtk_dialog_run(GTK_DIALOG(fs_dialog)) == GTK_RESPONSE_ACCEPT) { @@ -1310,13 +1311,7 @@ static void pick_import_files(GtkWidget *w, GSList **filelist) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs_dialog), current_def_dir); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fs_dialog), TRUE); - filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filter, "*.xml"); - gtk_file_filter_add_pattern(filter, "*.XML"); - gtk_file_filter_add_pattern(filter, "*.sda"); - gtk_file_filter_add_pattern(filter, "*.SDA"); - gtk_file_filter_add_mime_type(filter, "text/xml"); - gtk_file_filter_set_name(filter, "XML file"); + filter = setup_filter(); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fs_dialog), filter); gtk_widget_show_all(fs_dialog); if (gtk_dialog_run(GTK_DIALOG(fs_dialog)) == GTK_RESPONSE_ACCEPT) -- cgit v1.2.3-70-g09d2 From cc42debb8881e3e663defdcae2529ef9a62fbd6b Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 17:49:29 -0700 Subject: Mark divelist unchanged after closing the datafile This seems rather obvious - I'm surprised I didn't notice it earlier. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gtk-gui.c b/gtk-gui.c index 3833b5892..49dc36f12 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -252,6 +252,7 @@ static void file_close(GtkWidget *w, gpointer data) free(get_dive(i)); dive_table.nr = 0; dive_table.preexisting = 0; + mark_divelist_changed(FALSE); /* inlined version of g_list_free_full(dive_trip_list, free); */ g_list_foreach(dive_trip_list, (GFunc)free, NULL); -- cgit v1.2.3-70-g09d2 From 0d637c2fa915d13af8e00d5f236d3f111101c6e3 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 18:05:43 -0700 Subject: Show the datafile name even with no dives That's especially useful if starting without a filename and without an existing default file - this way it's clear that Subsurface still considers itself synced with the default file. Signed-off-by: Dirk Hohndel --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 46e22041d..d66972cdc 100644 --- a/main.c +++ b/main.c @@ -246,7 +246,7 @@ int main(int argc, char **argv) set_filename(filename, FALSE); } report_dives(imported); - + show_dive_info(NULL); run_ui(); exit_ui(); return 0; -- cgit v1.2.3-70-g09d2 From 421366d0fb52db317276ec404adb0c45cf398f29 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 18:32:15 -0700 Subject: Correctly deal with empty XML files Previously we could end up with a bogus dive with all zero data in it. Adding dives/test24.xml to be able to test that we handle this case correctly. Signed-off-by: Dirk Hohndel --- dives/test24.xml | 4 ++++ parse-xml.c | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 dives/test24.xml diff --git a/dives/test24.xml b/dives/test24.xml new file mode 100644 index 000000000..8ddc9be42 --- /dev/null +++ b/dives/test24.xml @@ -0,0 +1,4 @@ + + + + diff --git a/parse-xml.c b/parse-xml.c index a4ae81b25..f47ac5a26 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1173,11 +1173,23 @@ static void try_to_fill_trip(struct dive **divep, const char *name, char *buf) } /* - * File boundaries are dive boundaries. But sometimes there are + * While in some formats file boundaries are dive boundaries, in many + * others (as for example in our native format) there are * multiple dives per file, so there can be other events too that * trigger a "new dive" marker and you may get some nesting due * to that. Just ignore nesting levels. + * On the flipside it is possible that we start an XML file that ends + * up having no dives in it at all - don't create a bogus empty dive + * for those. It's not entirely clear what is the minimum set of data + * to make a dive valid, but if it has no location, no date and no + * samples I'm pretty sure it's useless. */ +static gboolean is_dive(void) +{ + return (cur_dive && + (cur_dive->location || cur_dive->when || cur_dive->samples)); +} + static void dive_start(void) { if (cur_dive) @@ -1188,7 +1200,7 @@ static void dive_start(void) static void dive_end(void) { - if (!cur_dive) + if (!is_dive()) return; record_dive(cur_dive); cur_dive = NULL; -- cgit v1.2.3-70-g09d2 From fa2f1b6eb06e65e6426cc3a488c6cb5c960e7d49 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 20:47:53 -0700 Subject: Fix potential crash when importing dives If the last of the preexisting dives gets merged with a new dive we end up dereferencing a freed pointer. Signed-off-by: Dirk Hohndel --- main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.c b/main.c index d66972cdc..3d9b43b41 100644 --- a/main.c +++ b/main.c @@ -125,6 +125,9 @@ void report_dives(gboolean is_imported) if (!merged) continue; + /* careful - we might free the dive that last points to. Oops... */ + if (last == prev || last == dive) + last = merged; free(prev); free(dive); *pp = merged; -- cgit v1.2.3-70-g09d2 From 7148dea82795b81311c46dfb11d09c8fa2b13452 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 15 Sep 2012 20:51:06 -0700 Subject: Once again improve existing filename handling Several potential problems. - we could end up dereferencing exiting_filename when it was NULL - we could free the default_filename by mistake - subsurface_default_filename always needs to return a copy of it - closing the existing file before opening a new one repopulated the existing_filename with the default filename - preventing the opened file to become the new existing filename Also, make existing filename a const char * and make file_open have the same sensible default folder behavior as the other file related functions. Signed-off-by: Dirk Hohndel --- dive.h | 2 +- gtk-gui.c | 27 +++++++++++++++++++-------- linux.c | 2 +- macos.c | 2 +- windows.c | 2 +- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/dive.h b/dive.h index 85d4b9fa4..177897099 100644 --- a/dive.h +++ b/dive.h @@ -463,7 +463,7 @@ const char *monthname(int mon); extern const char *star_strings[]; extern const char *default_filename; -extern char *existing_filename; +extern const char *existing_filename; extern const char *subsurface_default_filename(void); #define AIR_PERMILLE 209 diff --git a/gtk-gui.c b/gtk-gui.c index 49dc36f12..9b15cb4ee 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -25,7 +25,7 @@ GtkWidget *vpane, *hpane; GtkWidget *notebook; int error_count; -char *existing_filename; +const char *existing_filename; const char *divelist_font; const char *default_filename; @@ -154,8 +154,14 @@ static void file_save_as(GtkWidget *w, gpointer data) NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); - current_dir = g_path_get_dirname(existing_filename); - current_file = g_path_get_basename(existing_filename); + if (existing_filename) { + current_dir = g_path_get_dirname(existing_filename); + current_file = g_path_get_basename(existing_filename); + } else { + const char *current_default = subsurface_default_filename(); + current_dir = g_path_get_dirname(current_default); + current_file = g_path_get_basename(current_default); + } gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), current_dir); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), current_file); @@ -244,7 +250,7 @@ static void file_close(GtkWidget *w, gpointer data) return; if (existing_filename) - free(existing_filename); + free((void *)existing_filename); existing_filename = NULL; /* free the dives and trips */ @@ -278,9 +284,12 @@ static void file_open(GtkWidget *w, gpointer data) { GtkWidget *dialog; GtkFileFilter *filter; + const char *current_default; - /* first, close the existing file, if any */ + /* first, close the existing file, if any, and forget its name */ file_close(w, data); + free((void *)existing_filename); + existing_filename = NULL; dialog = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(main_window), @@ -288,6 +297,8 @@ static void file_open(GtkWidget *w, gpointer data) GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); + current_default = subsurface_default_filename(); + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), current_default); /* when opening the data file we should allow only one file to be chosen */ gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); @@ -669,7 +680,7 @@ static void preferences_dialog(GtkWidget *w, gpointer data) * update existing_filename */ if (existing_filename) { if (strcmp(current_default, existing_filename) == 0) { - free(existing_filename); + free((void *)existing_filename); existing_filename = strdup(new_default); } } @@ -1081,7 +1092,7 @@ void exit_ui(void) if (default_filename) free((char *)default_filename); if (existing_filename) - free(existing_filename); + free((void *)existing_filename); } typedef struct { @@ -1469,7 +1480,7 @@ void set_filename(const char *filename, gboolean force) { if (!force && existing_filename) return; - free(existing_filename); + free((void *)existing_filename); if (filename) existing_filename = strdup(filename); } diff --git a/linux.c b/linux.c index 8d9f6f8ce..47a00a059 100644 --- a/linux.c +++ b/linux.c @@ -69,7 +69,7 @@ const char *subsurface_icon_name() const char *subsurface_default_filename() { if (default_filename) { - return default_filename; + return strdup(default_filename); } else { const char *home, *user; char *buffer; diff --git a/macos.c b/macos.c index d37b0a925..d76225472 100644 --- a/macos.c +++ b/macos.c @@ -89,7 +89,7 @@ const char *subsurface_icon_name() const char *subsurface_default_filename() { if (default_filename) { - return default_filename; + return strdup(default_filename); } else { const char *home, *user; char *buffer; diff --git a/windows.c b/windows.c index 87bcaf6bd..b6e10bb71 100644 --- a/windows.c +++ b/windows.c @@ -98,7 +98,7 @@ const char *subsurface_icon_name() const char *subsurface_default_filename() { if (default_filename) { - return default_filename; + return strdup(default_filename); } else { char datapath[MAX_PATH]; const char *user; -- cgit v1.2.3-70-g09d2 From 46d91acdffd9a7d9d54fce5d72a07bfc62100b02 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 16 Sep 2012 05:01:25 -0400 Subject: Don't close existing data file in file_open if user cancels This logic seems to make much more sense - if the user hits 'OK' then the old file is closed and the new one openened. Otherwise, leave things unchanged. Reported-by: Miika Turkia Signed-off-by: Dirk Hohndel --- gtk-gui.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index 9b15cb4ee..27bf30cc4 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -286,11 +286,6 @@ static void file_open(GtkWidget *w, gpointer data) GtkFileFilter *filter; const char *current_default; - /* first, close the existing file, if any, and forget its name */ - file_close(w, data); - free((void *)existing_filename); - existing_filename = NULL; - dialog = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_OPEN, @@ -308,6 +303,12 @@ static void file_open(GtkWidget *w, gpointer data) if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { GSList *filenames, *fn_glist; char *filename; + + /* first, close the existing file, if any, and forget its name */ + file_close(w, data); + free((void *)existing_filename); + existing_filename = NULL; + filenames = fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); GError *error = NULL; -- cgit v1.2.3-70-g09d2 From 2cadc70e3dc521b0b208587b5a9121378ff855e5 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 16 Sep 2012 05:05:53 -0400 Subject: Simplify code in file_open as we now only open one file This doesn't change functionality - it's just pointless to loop over a list that is known to have only one element. Signed-off-by: Dirk Hohndel --- gtk-gui.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/gtk-gui.c b/gtk-gui.c index 27bf30cc4..c440eb2e7 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -301,7 +301,7 @@ static void file_open(GtkWidget *w, gpointer data) gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - GSList *filenames, *fn_glist; + GSList *fn_glist; char *filename; /* first, close the existing file, if any, and forget its name */ @@ -309,22 +309,19 @@ static void file_open(GtkWidget *w, gpointer data) free((void *)existing_filename); existing_filename = NULL; - filenames = fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + /* we know there is only one filename */ + fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); GError *error = NULL; - while(filenames != NULL) { - filename = filenames->data; - parse_file(filename, &error); - if (error != NULL) - { - report_error(error); - g_error_free(error); - error = NULL; - } - - g_free(filename); - filenames = g_slist_next(filenames); + filename = fn_glist->data; + parse_file(filename, &error); + if (error != NULL) + { + report_error(error); + g_error_free(error); + error = NULL; } + g_free(filename); g_slist_free(fn_glist); report_dives(FALSE); } -- cgit v1.2.3-70-g09d2 From d7465129bb7fc912ec89671051192983b80711c4 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 16 Sep 2012 06:04:37 -0400 Subject: Make sure dive info is displayed correctly at start Commit cdae2869d1dd ("Show the datafile name even with no dives") was a little too aggressive in making sure that we show the correct window title - we only should call show_dive_info(NULL) if there is indeed no dive in the dive table - otherwise we display empty dive info at program start. Signed-off-by: Dirk Hohndel --- main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 3d9b43b41..2bdccd277 100644 --- a/main.c +++ b/main.c @@ -249,7 +249,8 @@ int main(int argc, char **argv) set_filename(filename, FALSE); } report_dives(imported); - show_dive_info(NULL); + if (dive_table.nr == 0) + show_dive_info(NULL); run_ui(); exit_ui(); return 0; -- cgit v1.2.3-70-g09d2