]> git.tdb.fi Git - ext/subsurface.git/commitdiff
Merge branch 'quit-handling' of git://github.com/dirkhh/subsurface
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 21 Sep 2011 19:28:20 +0000 (12:28 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 21 Sep 2011 19:28:20 +0000 (12:28 -0700)
* 'quit-handling' of git://github.com/dirkhh/subsurface:
  Use the last (or only) filename on command line as default for saving
  Show the "save changes" dialog before the main window is destroyed
  Check for changes at regular 'quit' events as well
  Catch changes to the info of the current dive when quitting
  Tracking changes to tanks is trivial
  Simplistic first attempt to get changes saved when quitting subsurface

dive.h
divelist.c
divelist.h
equipment.c
gtk-gui.c
info.c
parse-xml.c

diff --git a/dive.h b/dive.h
index fc458d04d4292df0a36bf99428c84b66c169aad2..e1a5bc007e69fe76d032a2c81ce80dcb80897034 100644 (file)
--- 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 *);
index 88825dd8913465c13d532e05bb638e4f20abb878..e84e3a10de084590f377be1f602247db556e2190 100644 (file)
@@ -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;
+}
index 7684a72d3e8e8d337666971b4cbe676c3f74f62f..3151a69dbcab1453ab6c2fe523c2be922247ea01 100644 (file)
@@ -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
index 1e0721b9abd195370b6daa8ecdb81f2938cf70d4..5d5a3546cc7f090116c2372419e26089dce69a8b 100644 (file)
@@ -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);
 }
 
index f60df9bf161d8565bc3c8416a29c84550e2a188d..3994387acdf5f42f632451152e48b42671c4dde0 100644 (file)
--- 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 9e061970d808ba14bb18d9c259de638781b0c0af..e79a80b38193e65b0cdc17d1170bc2aaea83faf5 100644 (file)
--- 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) \
index 22ab8458e1f5871d932d4d5666c5df7ccc1a94dc..1eb6e95fdd1007aff73d326c7d6b073c7fe36f36 100644 (file)
@@ -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));