1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007 Free Software Foundation
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* This file is a rubbish bin where stuff gets put when it doesn't seem to
23 #include "psppire-syntax-window.h"
25 #include <glib-object.h>
29 #include "message-dialog.h"
30 #include <data/format.h>
31 #include <data/data-in.h>
32 #include <data/data-out.h>
33 #include <data/dictionary.h>
34 #include <data/casereader-provider.h>
35 #include <libpspp/message.h>
37 #include <gtk/gtkbuilder.h>
38 #include <libpspp/i18n.h>
43 #include <data/settings.h>
45 #include <language/command.h>
46 #include <data/lazy-casereader.h>
47 #include <data/procedure.h>
48 #include <language/lexer/lexer.h>
49 #include "psppire-data-store.h"
50 #include <output/manager.h>
51 #include "psppire-output-window.h"
57 /* Formats a value according to FORMAT
58 The returned string must be freed when no longer required */
60 value_to_text (union value v, struct fmt_spec format)
64 s = g_new (gchar, format.w + 1);
65 data_out (&v, &format, s);
75 text_to_value (const gchar *text, union value *v,
76 struct fmt_spec format)
80 if ( format.type != FMT_A)
82 if ( ! text ) return FALSE;
85 const gchar *s = text;
93 if ( !*s) return FALSE;
98 ok = data_in (ss_cstr (text), LEGACY_NATIVE, format.type, 0, 0, 0,
99 v, fmt_var_width (&format));
107 builder_new_real (const gchar *name)
109 GtkBuilder *builder = gtk_builder_new ();
112 if ( ! gtk_builder_add_from_file (builder, name, &err))
114 g_critical ("Couldnt open user interface file %s: %s", name, err->message);
115 g_clear_error (&err);
123 get_object_assert (GtkBuilder *builder, const gchar *name, GType type)
128 o = gtk_builder_get_object (builder, name);
131 g_critical ("Object \"%s\" could not be found\n", name);
133 if ( ! g_type_is_a (G_OBJECT_TYPE (o), type))
135 g_critical ("Object \"%s\" was expected to have type %s, but in fact has type %s",
136 name, g_type_name (type), G_OBJECT_TYPE_NAME (o));
144 get_action_assert (GtkBuilder *builder, const gchar *name)
146 return GTK_ACTION (get_object_assert (builder, name, GTK_TYPE_ACTION));
150 get_widget_assert (GtkBuilder *builder, const gchar *name)
152 return GTK_WIDGET (get_object_assert (builder, name, GTK_TYPE_WIDGET));
155 /* This function must be used whenever a filename generated by glib,
156 (eg, from gtk_file_chooser_get_filename) and passed to the C library,
157 (eg through a pspp syntax string).
160 convert_glib_filename_to_system_filename (const gchar *fname, GError **err)
165 const gchar *target_encoding;
166 gchar *utf8_name = NULL;
168 g_get_charset (&target_encoding);
170 output_name = g_convert (fname, -1, target_encoding,
171 "UTF-8", NULL, NULL, err);
173 output_name = strdup (fname);
181 #define _(msgid) gettext (msgid)
182 #define N_(msgid) msgid
190 dialog = gtk_message_dialog_new (NULL,
194 _("Sorry. The help system hasn't yet "
195 "been implemented."));
196 gtk_dialog_run (GTK_DIALOG (dialog));
197 gtk_widget_destroy (dialog);
201 connect_help (GtkBuilder *xml)
203 GSList *helps = gtk_builder_get_objects (xml);
206 for ( i = helps; i ; i = g_slist_next (i))
208 GObject *o = i->data;
209 if ( GTK_IS_WIDGET (o) )
213 g_object_get (o, "name", &name, NULL);
216 strncpy (s, name, 11);
220 if ( 0 == strcmp ("help_button", s))
222 g_signal_connect (o, "clicked", give_help, 0);
227 g_slist_free (helps);
232 reference_manual (GtkMenuItem *menu, gpointer data)
235 gchar *cmd = g_strdup_printf ("yelp file://%s", relocate (DOCDIR "/pspp.xml"));
237 if ( ! g_spawn_command_line_async (cmd, &err) )
239 msg (ME, _("Cannot open reference manual: %s"), err->message);
243 g_clear_error (&err);
247 extern struct dataset *the_dataset;
248 extern struct source_stream *the_source_stream;
249 extern PsppireDataStore *the_data_store;
251 /* Lazy casereader callback function used by execute_syntax. */
252 static struct casereader *
253 create_casereader_from_data_store (void *data_store_)
255 PsppireDataStore *data_store = data_store_;
256 return psppire_data_store_get_reader (data_store);
260 execute_syntax (struct getl_interface *sss)
263 gboolean retval = TRUE;
265 struct casereader *reader;
268 unsigned long int lazy_serial;
270 /* When the user executes a number of snippets of syntax in a
271 row, none of which read from the active file, the GUI becomes
272 progressively less responsive. The reason is that each syntax
273 execution encapsulates the active file data in another
274 datasheet layer. The cumulative effect of having a number of
275 layers of datasheets wastes time and space.
277 To solve the problem, we use a "lazy casereader", a wrapper
278 around the casereader obtained from the data store, that
279 only actually instantiates that casereader when it is
280 needed. If the data store casereader is never needed, then
281 it is reused the next time syntax is run, without wrapping
282 it in another layer. */
283 value_cnt = psppire_data_store_get_value_count (the_data_store);
284 case_cnt = psppire_data_store_get_case_count (the_data_store);
285 reader = lazy_casereader_create (value_cnt, case_cnt,
286 create_casereader_from_data_store,
287 the_data_store, &lazy_serial);
288 proc_set_active_file_data (the_dataset, reader);
290 g_return_val_if_fail (proc_has_active_file (the_dataset), FALSE);
292 lexer = lex_create (the_source_stream);
294 getl_append_source (the_source_stream, sss, GETL_BATCH, ERRMODE_CONTINUE);
298 enum cmd_result result = cmd_parse (lexer, the_dataset);
300 if ( cmd_result_is_failure (result))
303 if ( source_stream_current_error_mode (the_source_stream)
308 if ( result == CMD_EOF || result == CMD_FINISH)
312 getl_abort_noninteractive (the_source_stream);
316 psppire_dict_replace_dictionary (the_data_store->dict,
317 dataset_dict (the_dataset));
319 reader = proc_extract_active_file_data (the_dataset);
320 if (!lazy_casereader_destroy (reader, lazy_serial))
321 psppire_data_store_set_reader (the_data_store, reader);
325 psppire_output_window_reload ();
332 /* Create a deep copy of SRC */
334 clone_list_store (const GtkListStore *src)
336 GtkTreeIter src_iter;
339 const gint n_cols = gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
340 GType *types = g_malloc (sizeof (*types) * n_cols);
345 for (i = 0 ; i < n_cols; ++i )
346 types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
348 dest = gtk_list_store_newv (n_cols, types);
350 for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
353 ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
355 GtkTreeIter dest_iter;
356 gtk_list_store_append (dest, &dest_iter);
358 for (i = 0 ; i < n_cols; ++i )
362 gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
363 gtk_list_store_set_value (dest, &dest_iter, i, &val);
365 g_value_unset (&val);
377 paste_syntax_in_new_window (const gchar *syntax)
379 GtkWidget *se = psppire_syntax_window_new ();
381 gtk_text_buffer_insert_at_cursor (PSPPIRE_SYNTAX_WINDOW (se)->buffer, syntax, -1);
383 gtk_widget_show (se);