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 /* Converts a string in the pspp locale to utf-8.
156 The return value must be freed when no longer required*/
158 pspp_locale_to_utf8 (const gchar *text, gssize len, GError **err)
160 return recode_string (CONV_PSPP_TO_UTF8, text, len);
164 utf8_to_pspp_locale (const gchar *text, gssize len, GError **err)
166 return recode_string (CONV_UTF8_TO_PSPP, text, len);
169 /* This function must be used whenever a filename generated by glib,
170 (eg, from gtk_file_chooser_get_filename) and passed to the C library,
171 (eg through a pspp syntax string).
174 convert_glib_filename_to_system_filename (const gchar *fname, GError **err)
179 const gchar *target_encoding;
180 gchar *utf8_name = NULL;
182 g_get_charset (&target_encoding);
184 output_name = g_convert (fname, -1, target_encoding,
185 "UTF-8", NULL, NULL, err);
187 output_name = strdup (fname);
195 #define _(msgid) gettext (msgid)
196 #define N_(msgid) msgid
204 dialog = gtk_message_dialog_new (NULL,
208 _("Sorry. The help system hasn't yet "
209 "been implemented."));
210 gtk_dialog_run (GTK_DIALOG (dialog));
211 gtk_widget_destroy (dialog);
215 connect_help (GtkBuilder *xml)
217 GSList *helps = gtk_builder_get_objects (xml);
220 for ( i = helps; i ; i = g_slist_next (i))
222 GObject *o = i->data;
223 if ( GTK_IS_WIDGET (o) )
227 g_object_get (o, "name", &name, NULL);
230 strncpy (s, name, 11);
234 if ( 0 == strcmp ("help_button", s))
236 g_signal_connect (o, "clicked", give_help, 0);
241 g_slist_free (helps);
246 reference_manual (GtkMenuItem *menu, gpointer data)
249 gchar *cmd = g_strdup_printf ("yelp file://%s", relocate (DOCDIR "/pspp.xml"));
251 if ( ! g_spawn_command_line_async (cmd, &err) )
253 msg (ME, _("Cannot open reference manual: %s"), err->message);
257 g_clear_error (&err);
261 extern struct dataset *the_dataset;
262 extern struct source_stream *the_source_stream;
263 extern PsppireDataStore *the_data_store;
265 /* Lazy casereader callback function used by execute_syntax. */
266 static struct casereader *
267 create_casereader_from_data_store (void *data_store_)
269 PsppireDataStore *data_store = data_store_;
270 return psppire_data_store_get_reader (data_store);
274 execute_syntax (struct getl_interface *sss)
277 gboolean retval = TRUE;
279 struct casereader *reader;
282 unsigned long int lazy_serial;
284 /* When the user executes a number of snippets of syntax in a
285 row, none of which read from the active file, the GUI becomes
286 progressively less responsive. The reason is that each syntax
287 execution encapsulates the active file data in another
288 datasheet layer. The cumulative effect of having a number of
289 layers of datasheets wastes time and space.
291 To solve the problem, we use a "lazy casereader", a wrapper
292 around the casereader obtained from the data store, that
293 only actually instantiates that casereader when it is
294 needed. If the data store casereader is never needed, then
295 it is reused the next time syntax is run, without wrapping
296 it in another layer. */
297 value_cnt = psppire_data_store_get_value_count (the_data_store);
298 case_cnt = psppire_data_store_get_case_count (the_data_store);
299 reader = lazy_casereader_create (value_cnt, case_cnt,
300 create_casereader_from_data_store,
301 the_data_store, &lazy_serial);
302 proc_set_active_file_data (the_dataset, reader);
304 g_return_val_if_fail (proc_has_active_file (the_dataset), FALSE);
306 lexer = lex_create (the_source_stream);
308 getl_append_source (the_source_stream, sss, GETL_BATCH, ERRMODE_CONTINUE);
312 enum cmd_result result = cmd_parse (lexer, the_dataset);
314 if ( cmd_result_is_failure (result))
317 if ( source_stream_current_error_mode (the_source_stream)
322 if ( result == CMD_EOF || result == CMD_FINISH)
326 getl_abort_noninteractive (the_source_stream);
330 psppire_dict_replace_dictionary (the_data_store->dict,
331 dataset_dict (the_dataset));
333 reader = proc_extract_active_file_data (the_dataset);
334 if (!lazy_casereader_destroy (reader, lazy_serial))
335 psppire_data_store_set_reader (the_data_store, reader);
339 psppire_output_window_reload ();
346 /* Create a deep copy of SRC */
348 clone_list_store (const GtkListStore *src)
350 GtkTreeIter src_iter;
353 const gint n_cols = gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
354 GType *types = g_malloc (sizeof (*types) * n_cols);
359 for (i = 0 ; i < n_cols; ++i )
360 types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
362 dest = gtk_list_store_newv (n_cols, types);
364 for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
367 ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
369 GtkTreeIter dest_iter;
370 gtk_list_store_append (dest, &dest_iter);
372 for (i = 0 ; i < n_cols; ++i )
376 gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
377 gtk_list_store_set_value (dest, &dest_iter, i, &val);
379 g_value_unset (&val);
391 paste_syntax_in_new_window (const gchar *syntax)
393 GtkWidget *se = psppire_syntax_window_new ();
395 gtk_text_buffer_insert_at_cursor (PSPPIRE_SYNTAX_WINDOW (se)->buffer, syntax, -1);
397 gtk_widget_show (se);