Thanks to Ben for the review.
+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.
#include <libpspp/str.h>
#include <libpspp/taint.h>
+
struct dataset {
/* Cases are read from source,
their transformation variables are initialized,
/* 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;
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;
}
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
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.
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);
}
}
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
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)
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);
}
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 *);
+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
#include "helper.h"
#include "about.h"
+#include <data/procedure.h>
#include "psppire-dialog.h"
#include "psppire-selector.h"
#include "weight-cases-dialog.h"
}
+
+/* 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 *);
psppire_data_store_set_string (store, text, row, column);
}
+extern struct dataset *the_dataset;
+
/*
Create a new data editor.
*/
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"));
"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",
<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>
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);
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));
psppire_data_store_set_case_file (the_data_store, pcf);
}
-
- return status;
}
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) \