aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.h1
-rw-r--r--divelist.c18
-rw-r--r--divelist.h2
-rw-r--r--equipment.c1
-rw-r--r--gtk-gui.c55
-rw-r--r--info.c37
-rw-r--r--parse-xml.c4
7 files changed, 105 insertions, 13 deletions
diff --git a/dive.h b/dive.h
index fc458d04d..e1a5bc007 100644
--- a/dive.h
+++ b/dive.h
@@ -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);
}
diff --git a/gtk-gui.c b/gtk-gui.c
index f60df9bf1..3994387ac 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -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;
+}
diff --git a/info.c b/info.c
index 9e061970d..e79a80b38 100644
--- a/info.c
+++ b/info.c
@@ -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));