Unsaved indicator for data files.
authorJohn Darrington <john@darrington.wattle.id.au>
Mon, 23 Feb 2009 02:35:32 +0000 (11:35 +0900)
committerJohn Darrington <john@darrington.wattle.id.au>
Mon, 23 Feb 2009 02:35:32 +0000 (11:35 +0900)
Add callback to dictionary and dataset.  Use these callbacks
to set  a flag for the gui to indicate when a data file is
saved or not saved.

src/data/dictionary.c
src/data/dictionary.h
src/data/procedure.c
src/data/procedure.h
src/ui/gui/psppire-data-window.c

index 02c6aa76bc5c991a2bc077ed9bc91a3e60972eea..f6776780fe7362a61ec1545fa8037dada890c8e4 100644 (file)
@@ -66,8 +66,21 @@ struct dictionary
     const struct dict_callbacks *callbacks; /* Callbacks on dictionary
                                               modification */
     void *cb_data ;                  /* Data passed to callbacks */
+
+    void (*changed) (struct dictionary *, void *); /* Generic change callback */
+    void *changed_data;
   };
 
+void
+dict_set_change_callback (struct dictionary *d,
+                         void (*changed) (struct dictionary *, void*),
+                         void *data)
+{
+  d->changed = changed;
+  d->changed_data = data;
+}
+
+
 /* Print a representation of dictionary D to stdout, for
    debugging purposes. */
 void
@@ -334,6 +347,7 @@ add_var (struct dictionary *d, struct variable *v)
   d->var[d->var_cnt++] = v;
   hsh_force_insert (d->name_tab, v);
 
+  if ( d->changed ) d->changed (d, d->changed_data);
   if ( d->callbacks &&  d->callbacks->var_added )
     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
 
@@ -461,6 +475,7 @@ set_var_dict_index (struct variable *v, int dict_index)
   vdi.dict_index = dict_index;
   var_set_vardict (v, &vdi);
 
+  if ( d->changed ) d->changed (d, d->changed_data);
   if ( d->callbacks &&  d->callbacks->var_changed )
     d->callbacks->var_changed (d, dict_index, d->cb_data);
 }
@@ -535,7 +550,7 @@ dict_delete_var (struct dictionary *d, struct variable *v)
   var_clear_vardict (v);
   var_destroy (v);
 
-
+  if ( d->changed ) d->changed (d, d->changed_data);
   if (d->callbacks &&  d->callbacks->var_deleted )
     d->callbacks->var_deleted (d, dict_index, case_index, val_cnt, d->cb_data);
 }
@@ -666,6 +681,7 @@ dict_rename_var (struct dictionary *d, struct variable *v,
   if (settings_get_algorithm () == ENHANCED)
     var_clear_short_names (v);
 
+  if ( d->changed ) d->changed (d, d->changed_data);
   if ( d->callbacks &&  d->callbacks->var_changed )
     d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
 }
@@ -905,6 +921,7 @@ dict_set_weight (struct dictionary *d, struct variable *v)
 
   d->weight = v;
 
+  if (d->changed) d->changed (d, d->changed_data);
   if ( d->callbacks &&  d->callbacks->weight_changed )
     d->callbacks->weight_changed (d,
                                  v ? var_get_dict_index (v) : -1,
@@ -933,6 +950,7 @@ dict_set_filter (struct dictionary *d, struct variable *v)
 
   d->filter = v;
 
+  if (d->changed) d->changed (d, d->changed_data);
   if ( d->callbacks && d->callbacks->filter_changed )
     d->callbacks->filter_changed (d,
                                  v ? var_get_dict_index (v) : -1,
@@ -1087,6 +1105,7 @@ dict_unset_split_var (struct dictionary *d, struct variable *v)
                                &v, compare_var_ptrs, NULL);
   if (orig_count != d->split_cnt)
     {
+      if (d->changed) d->changed (d, d->changed_data);
       /* We changed the set of split variables so invoke the
          callback. */
       if (d->callbacks &&  d->callbacks->split_changed)
@@ -1114,6 +1133,7 @@ dict_set_split_vars (struct dictionary *d,
     d->split = NULL;
    }
 
+  if (d->changed) d->changed (d, d->changed_data);
   if ( d->callbacks &&  d->callbacks->split_changed )
     d->callbacks->split_changed (d, d->cb_data);
 }
@@ -1328,6 +1348,7 @@ dict_var_changed (const struct variable *v)
       const struct vardict_info *vdi = var_get_vardict (v);
       struct dictionary *d = vdi->dict;
 
+      if (d->changed ) d->changed (d, d->changed_data);
       if ( d->callbacks && d->callbacks->var_changed )
        d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
     }
@@ -1348,6 +1369,7 @@ dict_var_resized (const struct variable *v, int delta)
 
       dict_pad_values (d, var_get_case_index(v) + 1, delta);
 
+      if (d->changed) d->changed (d, d->changed_data);
       if ( d->callbacks && d->callbacks->var_resized )
        d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data);
     }
@@ -1365,6 +1387,7 @@ dict_var_display_width_changed (const struct variable *v)
 
       d = vdi->dict;
 
+      if (d->changed) d->changed (d, d->changed_data);
       if ( d->callbacks && d->callbacks->var_display_width_changed )
        d->callbacks->var_display_width_changed (d, var_get_dict_index (v), d->cb_data);
     }
index 682409e24216a11c7492cb39082b30d62f101f19..18bf3f781081a14fc23fe2d3568efa1e96b31a9c 100644 (file)
@@ -164,6 +164,11 @@ void dict_set_callbacks (struct dictionary *, const struct dict_callbacks *,
                         void *);
 void dict_copy_callbacks (struct dictionary *, const struct dictionary *);
 
+void dict_set_change_callback (struct dictionary *d,
+                              void (*changed) (struct dictionary *, void*),
+                              void *data);
+
+
 /* Debug use only. */
 void dict_dump (const struct dictionary *);
 
index 91e185a45a43f3d78802338d6b26536f0a9dc6b0..32839e6413356c42b61d238a6634c7c1894775ca 100644 (file)
@@ -92,6 +92,10 @@ struct dataset {
   proc_state;
   casenumber cases_written;       /* Cases output so far. */
   bool ok;                    /* Error status. */
+
+  void (*callback) (void *); /* Callback for when the dataset changes */
+  void *cb_data;
+
 }; /* struct dataset */
 
 
@@ -99,9 +103,24 @@ static void add_case_limit_trns (struct dataset *ds);
 static void add_filter_trns (struct dataset *ds);
 
 static void update_last_proc_invocation (struct dataset *ds);
+
+static void
+dataset_set_unsaved (const struct dataset *ds)
+{
+  if (ds->callback) ds->callback (ds->cb_data);
+}
+
 \f
 /* Public functions. */
 
+void
+dataset_set_callback (struct dataset *ds, void (*cb) (void *), void *cb_data)
+{
+  ds->callback = cb;
+  ds->cb_data = cb_data;
+}
+
+
 /* Returns the last time the data was read. */
 time_t
 time_of_last_procedure (struct dataset *ds)
@@ -293,6 +312,8 @@ proc_commit (struct dataset *ds)
   assert (ds->proc_state == PROC_CLOSED);
   ds->proc_state = PROC_COMMITTED;
 
+  dataset_set_unsaved (ds);
+
   /* Free memory for lagged cases. */
   while (!deque_is_empty (&ds->lag))
     case_unref (ds->lag_cases[deque_pop_back (&ds->lag)]);
@@ -510,12 +531,23 @@ proc_cancel_all_transformations (struct dataset *ds)
   return ok;
 }
 \f
+
+static void
+dict_callback (struct dictionary *d UNUSED, void *ds_)
+{
+  struct dataset *ds = ds_;
+  dataset_set_unsaved (ds);
+}
+
 /* Initializes procedure handling. */
 struct dataset *
 create_dataset (void)
 {
   struct dataset *ds = xzalloc (sizeof(*ds));
   ds->dict = dict_create ();
+
+  dict_set_change_callback (ds->dict, dict_callback, ds);
+
   ds->caseinit = caseinit_create ();
   proc_cancel_all_transformations (ds);
   return ds;
@@ -585,6 +617,7 @@ proc_set_active_file (struct dataset *ds,
 
   dict_destroy (ds->dict);
   ds->dict = dict;
+  dict_set_change_callback (ds->dict, dict_callback, ds);
 
   proc_set_active_file_data (ds, source);
 }
index 5d998030a644d8d20ac2f030f90a70e685959bb6..09d44eeef612bdda52072acbf8be40a8982f9a46 100644 (file)
@@ -85,4 +85,6 @@ const struct casereader *dataset_source (const struct dataset *ds);
 const struct ccase *lagged_case (const struct dataset *ds, int n_before);
 void dataset_need_lag (struct dataset *ds, int n_before);
 
+void dataset_set_callback (struct dataset *ds, void (*cb) (void *), void *);
+
 #endif /* procedure.h */
index cdd00dca1d46c6efb6bd8892295f29ae8bcb0b9a..40e41dccca4bc544dbc51d56d4e326d264170d19 100644 (file)
@@ -337,6 +337,8 @@ open_data_file (const gchar *file_name, PsppireDataWindow *de)
     psppire_window_set_filename (PSPPIRE_WINDOW (de), file_name);
     add_most_recent (file_name);
   }
+
+  psppire_window_set_unsaved (PSPPIRE_WINDOW (de), FALSE);
 }
 
 
@@ -454,6 +456,8 @@ save_file (PsppireDataWindow *de)
   ds_destroy (&file_name);
 
   execute_syntax (sss);
+
+  psppire_window_set_unsaved (PSPPIRE_WINDOW (de), FALSE);
 }
 
 
@@ -1000,7 +1004,11 @@ on_switch_sheet (GtkNotebook *notebook,
 }
 
 
-
+static void
+set_unsaved (gpointer w)
+{
+  psppire_window_set_unsaved (PSPPIRE_WINDOW (w), TRUE);
+}
 
 static void
 psppire_data_window_init (PsppireDataWindow *de)
@@ -1021,6 +1029,17 @@ psppire_data_window_init (PsppireDataWindow *de)
   de->data_editor =
     PSPPIRE_DATA_EDITOR (psppire_data_editor_new (the_var_store, the_data_store));
 
+  g_signal_connect_swapped (the_data_store, "case-changed",
+                   G_CALLBACK (set_unsaved), de);
+
+  g_signal_connect_swapped (the_data_store, "case-inserted",
+                   G_CALLBACK (set_unsaved), de);
+
+  g_signal_connect_swapped (the_data_store, "cases-deleted",
+                   G_CALLBACK (set_unsaved), de);
+
+  dataset_set_callback (the_dataset, set_unsaved, de);
+
   connect_help (de->xml);
 
   g_object_ref (menubar);