Patch #6086. Adds "transformation pending" state.
authorJohn Darrington <john@darrington.wattle.id.au>
Thu, 26 Jul 2007 02:02:22 +0000 (02:02 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Thu, 26 Jul 2007 02:02:22 +0000 (02:02 +0000)
Thanks to Ben for the review.

src/data/ChangeLog
src/data/procedure.c
src/data/procedure.h
src/ui/gui/ChangeLog
src/ui/gui/data-editor.c
src/ui/gui/data-editor.glade
src/ui/gui/helper.c
src/ui/gui/helper.h

index 70485fd915a70486243e6e7b670ce9df3b8753f5..ddf6e685bc51c2f64cb02812381853a1860e3891 100644 (file)
@@ -1,3 +1,8 @@
+2007-07-26 John Darrington <john@darrington.wattle.id.au>
+
+       * procedure.c procedure.h: Added callbacks which get invoked whenever 
+       a dataset's transformation chain changes.
+
 2007-07-24  Ben Pfaff  <blp@gnu.org>
 
        Fix bug #6113.
index 5f3ad2065a4037d2ebda033a6d5b26affcffe76f..6690490f30681ef129ab34cb86b033a5159aa701 100644 (file)
@@ -37,6 +37,7 @@
 #include <libpspp/str.h>
 #include <libpspp/taint.h>
 
+
 struct dataset {
   /* Cases are read from source,
      their transformation variables are initialized,
@@ -61,6 +62,11 @@ struct dataset {
   /* Callback which occurs whenever the DICT is replaced by a new one */
   replace_dictionary_callback *replace_dict;
 
+  /* Callback which occurs whenever the transformation chain(s) have
+     been modified */
+  transformation_change_callback_func *xform_callback;
+  void *xform_callback_aux;
+
   /* If true, cases are discarded instead of being written to
      sink. */
   bool discard_output;
@@ -384,6 +390,10 @@ proc_capture_transformations (struct dataset *ds)
   assert (ds->temporary_trns_chain == NULL);
   chain = ds->permanent_trns_chain;
   ds->cur_trns_chain = ds->permanent_trns_chain = trns_chain_create ();
+
+  if ( ds->xform_callback)
+    ds->xform_callback (false, ds->xform_callback_aux);
+
   return chain;
 }
 
@@ -394,6 +404,8 @@ void
 add_transformation (struct dataset *ds, trns_proc_func *proc, trns_free_func *free, void *aux)
 {
   trns_chain_append (ds->cur_trns_chain, NULL, proc, free, aux);
+  if ( ds->xform_callback)
+    ds->xform_callback (true, ds->xform_callback_aux);
 }
 
 /* Adds a transformation that processes a case with PROC and
@@ -408,6 +420,9 @@ add_transformation_with_finalizer (struct dataset *ds,
                                    trns_free_func *free, void *aux)
 {
   trns_chain_append (ds->cur_trns_chain, finalize, proc, free, aux);
+
+  if ( ds->xform_callback)
+    ds->xform_callback (true, ds->xform_callback_aux);
 }
 
 /* Returns the index of the next transformation.
@@ -442,6 +457,9 @@ proc_start_temporary_transformations (struct dataset *ds)
 
       trns_chain_finalize (ds->permanent_trns_chain);
       ds->temporary_trns_chain = ds->cur_trns_chain = trns_chain_create ();
+
+      if ( ds->xform_callback)
+       ds->xform_callback (true, ds->xform_callback_aux);
     }
 }
 
@@ -483,6 +501,10 @@ proc_cancel_temporary_transformations (struct dataset *ds)
       trns_chain_destroy (ds->temporary_trns_chain);
       ds->temporary_trns_chain = NULL;
 
+      if ( ds->xform_callback)
+       ds->xform_callback (!trns_chain_is_empty (ds->permanent_trns_chain),
+                           ds->xform_callback_aux);
+
       return true;
     }
   else
@@ -500,23 +522,35 @@ proc_cancel_all_transformations (struct dataset *ds)
   ok = trns_chain_destroy (ds->temporary_trns_chain) && ok;
   ds->permanent_trns_chain = ds->cur_trns_chain = trns_chain_create ();
   ds->temporary_trns_chain = NULL;
+  if ( ds->xform_callback)
+    ds->xform_callback (false, ds->xform_callback_aux);
+
   return ok;
 }
 \f
 /* Initializes procedure handling. */
 struct dataset *
-create_dataset (replace_source_callback *rps,
-               replace_dictionary_callback *rds)
+create_dataset (transformation_change_callback_func *cb, void *aux)
 {
   struct dataset *ds = xzalloc (sizeof(*ds));
   ds->dict = dict_create ();
   ds->caseinit = caseinit_create ();
-  ds->replace_source = rps;
-  ds->replace_dict = rds;
+  ds->xform_callback = cb;
+  ds->xform_callback_aux = aux;
   proc_cancel_all_transformations (ds);
   return ds;
 }
 
+
+void
+dataset_add_transform_change_callback (struct dataset *ds,
+                                      transformation_change_callback_func *cb,
+                                      void *aux)
+{
+  ds->xform_callback = cb;
+  ds->xform_callback_aux = aux;
+}
+
 /* Finishes up procedure handling. */
 void
 destroy_dataset (struct dataset *ds)
@@ -525,6 +559,9 @@ destroy_dataset (struct dataset *ds)
   dict_destroy (ds->dict);
   caseinit_destroy (ds->caseinit);
   trns_chain_destroy (ds->permanent_trns_chain);
+
+  if ( ds->xform_callback)
+    ds->xform_callback (false, ds->xform_callback_aux);
   free (ds);
 }
 
index 1b014e81cf158e2a879bd406c46668b27a2822c0..cfb8f218c5402cc5d26053003b7993d27f01cc10 100644 (file)
@@ -51,12 +51,14 @@ struct dictionary ;
 typedef void  replace_source_callback (struct casereader *);
 typedef void  replace_dictionary_callback (struct dictionary *);
 
+typedef void transformation_change_callback_func (bool non_empty, void *aux);
 
-struct dataset * create_dataset (replace_source_callback *,
-                                replace_dictionary_callback *);
-
+struct dataset * create_dataset (transformation_change_callback_func *, void *);
 void destroy_dataset (struct dataset *);
 
+void dataset_add_transform_change_callback (struct dataset *,
+                                           transformation_change_callback_func *, void *);
+
 void proc_discard_active_file (struct dataset *);
 void proc_set_active_file (struct dataset *,
                            struct casereader *, struct dictionary *);
index e0b6a971300024b4157e30cd8d6b4274264c764a..4f0a0949f140e3c4e37b21bc4dd7487e69fdea07 100644 (file)
@@ -1,3 +1,11 @@
+2007-07-26  John Darrington <john@darrington.wattle.id.au>
+
+       * helper.c helper.h (execute_syntax): removed implicit EXECUTE at end 
+       of commands.
+
+       * data-editor.c data-editor.glade: Added "Run Pending Transformations" 
+       menuitem.
+
 2007-07-25  John Darrington <john@darrington.wattle.id.au>
 
        * customentry.c: Redraw button in insensitive state, if the widget's 
index 94094dff93ba17ed58c9b42428b06b4bcbeb3b5c..9681a09f1be8813e1e14d7696839afd8f39cf743 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "helper.h"
 #include "about.h"
+#include <data/procedure.h>
 #include "psppire-dialog.h"
 #include "psppire-selector.h"
 #include "weight-cases-dialog.h"
@@ -119,6 +120,37 @@ enable_delete_variables (GtkWidget *w, gint var, gpointer data)
 }
 
 
+
+/* Run the EXECUTE command. */
+static void
+execute (GtkMenuItem *mi, gpointer data)
+{
+  struct getl_interface *sss = create_syntax_string_source ("EXECUTE.");
+
+  execute_syntax (sss);
+}
+
+static void
+transformation_change_callback (bool transformations_pending,
+                               gpointer data)
+{
+  struct data_editor *de = data;
+  GtkWidget *menuitem =
+    get_widget_assert (de->xml, "transform_run-pending");
+  GtkWidget *status_label  =
+    get_widget_assert (de->xml, "case-counter-area");
+
+  gtk_widget_set_sensitive (menuitem, transformations_pending);
+
+
+  if ( transformations_pending)
+    gtk_label_set_text (GTK_LABEL (status_label),
+                       _("Transformations Pending"));
+  else
+    gtk_label_set_text (GTK_LABEL (status_label), "");
+}
+
+
 static void open_data_file (const gchar *, struct data_editor *);
 
 
@@ -184,6 +216,8 @@ datum_entry_activate (GtkEntry *entry, gpointer data)
   psppire_data_store_set_string (store, text, row, column);
 }
 
+extern struct dataset *the_dataset;
+
 /*
   Create a new data editor.
 */
@@ -203,6 +237,11 @@ new_data_editor (void)
 
   de->xml = XML_NEW ("data-editor.glade");
 
+
+  dataset_add_transform_change_callback (the_dataset,
+                                        transformation_change_callback,
+                                        de);
+
   var_sheet = GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
   data_sheet = GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
 
@@ -614,6 +653,10 @@ new_data_editor (void)
                    "activate",
                    G_CALLBACK (file_quit), de);
 
+  g_signal_connect (get_widget_assert (de->xml, "transform_run-pending"),
+                   "activate",
+                   G_CALLBACK (execute), de);
+
 
   g_signal_connect (get_widget_assert (de->xml, "windows_minimise_all"),
                    "activate",
index 18e3400164d20d5dfd6a90a1b36193a2b064f627..68813e02a1cb23aa88079e43de0b47e25e016f3b 100644 (file)
                         <property name="use_underline">True</property>
                       </widget>
                     </child>
+                 <child>
+                   <widget class="GtkSeparatorMenuItem" id="separator7">
+                     <property name="visible">True</property>
+                   </widget>
+                 </child>
+
+                 <child>
+                   <widget class="GtkMenuItem" id="transform_run-pending">
+                     <property name="visible">True</property>
+                     <property name="sensitive">False</property>
+                     <property name="label" translatable="yes">_Run Pending Transforms</property>
+                     <property name="use_underline">True</property>
+                     <accelerator key="G" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+                   </widget>
+                 </child>
+
                   </widget>
                 </child>
               </widget>
                     <child>
                       <widget class="GtkLabel" id="case-counter-area">
                         <property name="visible">True</property>
-                        <property name="width_chars">10</property>
+                        <property name="width_chars">25</property>
                         <property name="single_line_mode">True</property>
                       </widget>
                     </child>
index 09711f1bd1a39f4d51aa3f764fbba901ec862a58..5668496833cdd975d1874be4c345de0db54e67d0 100644 (file)
@@ -164,17 +164,16 @@ extern struct dataset *the_dataset;
 extern struct source_stream *the_source_stream;
 extern PsppireDataStore *the_data_store;
 
-gboolean
+void
 execute_syntax (struct getl_interface *sss)
 {
-  gboolean status;
   struct lexer *lexer;
 
   struct casereader *reader = psppire_data_store_get_reader (the_data_store);
 
   proc_set_active_file_data (the_dataset, reader);
 
-  g_return_val_if_fail (proc_has_active_file (the_dataset), FALSE);
+  g_return_if_fail (proc_has_active_file (the_dataset));
 
   lexer = lex_create (the_source_stream);
 
@@ -192,11 +191,6 @@ execute_syntax (struct getl_interface *sss)
 
   lex_destroy (lexer);
 
-  /* GUI syntax needs this implicit EXECUTE command at the end of
-     every script.  Otherwise commands like GET could leave the GUI
-     without a datasheet. */
-  status = proc_execute (the_dataset);
-
   psppire_dict_replace_dictionary (the_data_store->dict,
                                   dataset_dict (the_dataset));
 
@@ -205,8 +199,6 @@ execute_syntax (struct getl_interface *sss)
 
     psppire_data_store_set_case_file (the_data_store, pcf);
   }
-
-  return status;
 }
 
 
index ddced00fc3d61c15e72d85d31d087dc56e1413e1..7ada5b5298fe5bdb660a52995f3a7e4830aa5a76 100644 (file)
@@ -54,7 +54,7 @@ void connect_help (GladeXML *);
 void reference_manual (GtkMenuItem *, gpointer);
 
 struct getl_interface;
-gboolean execute_syntax (struct getl_interface *sss);
+void execute_syntax (struct getl_interface *sss);
 
 
 #define XML_NEW(FILE) \