diff options
-rw-r--r-- | dive.h | 1 | ||||
-rw-r--r-- | divelist.c | 18 | ||||
-rw-r--r-- | divelist.h | 2 | ||||
-rw-r--r-- | equipment.c | 1 | ||||
-rw-r--r-- | gtk-gui.c | 55 | ||||
-rw-r--r-- | info.c | 37 | ||||
-rw-r--r-- | parse-xml.c | 4 |
7 files changed, 105 insertions, 13 deletions
@@ -197,6 +197,7 @@ static inline struct dive *get_dive(unsigned int nr) extern void parse_xml_init(void); extern void parse_xml_file(const char *filename, GError **error); +extern void set_filename(const char *filename); extern void show_dive_info(struct dive *); extern void flush_dive_info_changes(struct dive *); diff --git a/divelist.c b/divelist.c index 88825dd89..e84e3a10d 100644 --- a/divelist.c +++ b/divelist.c @@ -7,6 +7,8 @@ * void dive_list_update_dives(void) * void update_dive_list_units(void) * void set_divelist_font(const char *font) + * void mark_divelist_changed(int changed) + * int unsaved_changes() */ #include <stdio.h> #include <stdlib.h> @@ -24,6 +26,7 @@ struct DiveList { GtkListStore *model; GtkTreeViewColumn *date, *depth, *duration, *location; GtkTreeViewColumn *temperature, *cylinder, *nitrox, *sac; + int changed; }; static struct DiveList dive_list; @@ -45,9 +48,6 @@ enum { DIVELIST_COLUMNS }; -/* the global dive list that we maintain */ -static struct DiveList dive_list; - static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model) { GtkTreeIter iter; @@ -492,5 +492,17 @@ GtkWidget *dive_list_create(void) GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(dive_list.container_widget), dive_list.tree_view); + dive_list.changed = 0; + return dive_list.container_widget; } + +void mark_divelist_changed(int changed) +{ + dive_list.changed = changed; +} + +int unsaved_changes() +{ + return dive_list.changed; +} diff --git a/divelist.h b/divelist.h index 7684a72d3..3151a69db 100644 --- a/divelist.h +++ b/divelist.h @@ -7,4 +7,6 @@ extern void dive_list_update_dives(void); extern void update_dive_list_units(void); extern void flush_divelist(struct dive *); +extern void mark_divelist_changed(int); +extern int unsaved_changes(void); #endif diff --git a/equipment.c b/equipment.c index 1e0721b9a..5d5a3546c 100644 --- a/equipment.c +++ b/equipment.c @@ -249,6 +249,7 @@ static void apply_cb(GtkButton *button, gpointer data) for (i = 0; i < MAX_CYLINDERS; i++) record_cylinder_changes(dive->cylinder+i, gtk_cylinder+i); + mark_divelist_changed(TRUE); flush_divelist(dive); } @@ -31,11 +31,6 @@ struct units output_units; #define GCONF_NAME(x) "/apps/subsurface/" #x -void on_destroy(GtkWidget* w, gpointer data) -{ - gtk_main_quit(); -} - static GtkWidget *dive_profile; void repaint_dive(void) @@ -146,12 +141,53 @@ static void file_save(GtkWidget *w, gpointer data) filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); save_dives(filename); g_free(filename); + mark_divelist_changed(FALSE); + } + gtk_widget_destroy(dialog); +} + +static void ask_save_changes() +{ + GtkWidget *dialog, *label, *content; + dialog = gtk_dialog_new_with_buttons("Save Changes?", + GTK_WINDOW(main_window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + NULL); + content = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + label = gtk_label_new ("You have unsaved changes\nWould you like to save those before exiting the program?"); + gtk_container_add (GTK_CONTAINER (content), label); + gtk_widget_show_all (dialog); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + file_save(NULL,NULL); } gtk_widget_destroy(dialog); } +static gboolean on_delete(GtkWidget* w, gpointer data) +{ + /* Make sure to flush any modified dive data */ + update_dive(NULL); + + if (unsaved_changes()) + ask_save_changes(); + + return FALSE; /* go ahead, kill the program, we're good now */ +} + +static void on_destroy(GtkWidget* w, gpointer data) +{ + gtk_main_quit(); +} + static void quit(GtkWidget *w, gpointer data) { + /* Make sure to flush any modified dive data */ + update_dive(NULL); + + if (unsaved_changes()) + ask_save_changes(); gtk_main_quit(); } @@ -387,6 +423,7 @@ void init_ui(int argc, char **argv) error_info_bar = NULL; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_icon_from_file(GTK_WINDOW(win), "icon.svg", NULL); + g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK (on_delete), NULL); g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL); main_window = win; @@ -614,3 +651,11 @@ void update_progressbar(progressbar_t *progress, double value) { gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress->bar), value); } + + +void set_filename(const char *filename) +{ + if (filename) + existing_filename = strdup(filename); + return; +} @@ -33,30 +33,59 @@ static char *get_text(GtkTextBuffer *buffer) return gtk_text_buffer_get_text(buffer, &start, &end, FALSE); } +/* old is NULL or a valid string, new is a valid string + * NOTW: NULL and "" need to be treated as "unchanged" */ +static int text_changed(char *old, char *new) +{ + return ((old && strcmp(old,new)) || + (!old && strcmp("",new))); +} + void flush_dive_info_changes(struct dive *dive) { + char *old_text; + int changed = 0; + if (!dive) return; if (location_changed) { - g_free(dive->location); + old_text = dive->location; dive->location = gtk_editable_get_chars(GTK_EDITABLE(location), 0, -1); + if (text_changed(old_text,dive->location)) + changed = 1; + if (old_text) + g_free(old_text); } if (divemaster_changed) { - g_free(dive->divemaster); + old_text = dive->divemaster; dive->divemaster = gtk_editable_get_chars(GTK_EDITABLE(divemaster), 0, -1); + if (text_changed(old_text,dive->divemaster)) + changed = 1; + if (old_text) + g_free(old_text); } if (buddy_changed) { - g_free(dive->buddy); + old_text = dive->buddy; dive->buddy = gtk_editable_get_chars(GTK_EDITABLE(buddy), 0, -1); + if (text_changed(old_text,dive->buddy)) + changed = 1; + if (old_text) + g_free(old_text); } if (notes_changed) { - g_free(dive->notes); + old_text = dive->notes; dive->notes = get_text(notes); + if (text_changed(old_text,dive->notes)) + changed = 1; + if (old_text) + g_free(old_text); } + if (changed) + mark_divelist_changed(TRUE); } #define SET_TEXT_ENTRY(x) \ diff --git a/parse-xml.c b/parse-xml.c index 22ab8458e..1eb6e95fd 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1380,7 +1380,9 @@ void parse_xml_file(const char *filename, GError **error) } 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(filename); reset_all(); dive_start(); traverse(xmlDocGetRootElement(doc)); |