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)
128 o = gtk_builder_get_object (builder, name);
131 g_critical ("Object \"%s\" could not be found\n", name);
137 get_widget_assert (gpointer x, const gchar *name)
139 GObject *obj = G_OBJECT (x);
143 if (GTK_IS_BUILDER (obj))
144 w = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (obj), name));
146 if (GLADE_IS_XML (obj))
147 w = glade_xml_get_widget (GLADE_XML (obj), name);
150 g_critical ("Widget \"%s\" could not be found\n", name);
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);
163 #define _(msgid) gettext (msgid)
164 #define N_(msgid) msgid
172 dialog = gtk_message_dialog_new (NULL,
176 _("Sorry. The help system hasn't yet "
177 "been implemented."));
178 gtk_dialog_run (GTK_DIALOG (dialog));
179 gtk_widget_destroy (dialog);
183 connect_help_builder (GtkBuilder *xml)
185 GSList *helps = gtk_builder_get_objects (xml);
188 for ( i = helps; i ; i = g_slist_next (i))
190 GObject *o = i->data;
191 if ( GTK_IS_WIDGET (o) )
195 g_object_get (o, "name", &name, NULL);
198 strncpy (s, name, 11);
202 if ( 0 == strcmp ("help_button", s))
204 g_signal_connect (GTK_WIDGET (o), "clicked", give_help, 0);
209 g_slist_free (helps);
213 connect_help_glade (GladeXML *xml)
215 GList *helps = glade_xml_get_widget_prefix (xml, "help_button_");
218 for ( i = g_list_first (helps); i ; i = g_list_next (i))
219 g_signal_connect (GTK_WIDGET (i->data), "clicked", give_help, 0);
226 connect_help (gpointer *xml)
228 if (GTK_IS_BUILDER (xml))
229 connect_help_builder (GTK_BUILDER (xml));
231 else if (GLADE_IS_XML (xml))
232 connect_help_glade (GLADE_XML (xml));
236 g_error ("XML of type %s", G_OBJECT_TYPE_NAME (xml));
243 reference_manual (GtkMenuItem *menu, gpointer data)
246 if ( ! g_spawn_command_line_async ("yelp info:pspp", &err) )
248 msg (ME, _("Cannot open reference manual: %s"), err->message);
250 g_clear_error (&err);
254 extern struct dataset *the_dataset;
255 extern struct source_stream *the_source_stream;
256 extern PsppireDataStore *the_data_store;
258 /* Lazy casereader callback function used by execute_syntax. */
259 static struct casereader *
260 create_casereader_from_data_store (void *data_store_)
262 PsppireDataStore *data_store = data_store_;
263 return psppire_data_store_get_reader (data_store);
267 execute_syntax (struct getl_interface *sss)
270 gboolean retval = TRUE;
272 struct casereader *reader;
275 unsigned long int lazy_serial;
277 /* When the user executes a number of snippets of syntax in a
278 row, none of which read from the active file, the GUI becomes
279 progressively less responsive. The reason is that each syntax
280 execution encapsulates the active file data in another
281 datasheet layer. The cumulative effect of having a number of
282 layers of datasheets wastes time and space.
284 To solve the problem, we use a "lazy casereader", a wrapper
285 around the casereader obtained from the data store, that
286 only actually instantiates that casereader when it is
287 needed. If the data store casereader is never needed, then
288 it is reused the next time syntax is run, without wrapping
289 it in another layer. */
290 value_cnt = psppire_data_store_get_value_count (the_data_store);
291 case_cnt = psppire_data_store_get_case_count (the_data_store);
292 reader = lazy_casereader_create (value_cnt, case_cnt,
293 create_casereader_from_data_store,
294 the_data_store, &lazy_serial);
295 proc_set_active_file_data (the_dataset, reader);
297 g_return_val_if_fail (proc_has_active_file (the_dataset), FALSE);
299 lexer = lex_create (the_source_stream);
301 getl_append_source (the_source_stream, sss, GETL_BATCH, ERRMODE_CONTINUE);
305 enum cmd_result result = cmd_parse (lexer, the_dataset);
307 if ( cmd_result_is_failure (result))
310 if ( source_stream_current_error_mode (the_source_stream)
315 if ( result == CMD_EOF || result == CMD_FINISH)
319 getl_abort_noninteractive (the_source_stream);
323 psppire_dict_replace_dictionary (the_data_store->dict,
324 dataset_dict (the_dataset));
326 reader = proc_extract_active_file_data (the_dataset);
327 if (!lazy_casereader_destroy (reader, lazy_serial))
328 psppire_data_store_set_reader (the_data_store, reader);
332 psppire_output_window_reload ();
339 /* Create a deep copy of SRC */
341 clone_list_store (const GtkListStore *src)
343 GtkTreeIter src_iter;
346 const gint n_cols = gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
347 GType *types = g_malloc (sizeof (*types) * n_cols);
352 for (i = 0 ; i < n_cols; ++i )
353 types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
355 dest = gtk_list_store_newv (n_cols, types);
357 for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
360 ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
362 GtkTreeIter dest_iter;
363 gtk_list_store_append (dest, &dest_iter);
365 for (i = 0 ; i < n_cols; ++i )
369 gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
370 gtk_list_store_set_value (dest, &dest_iter, i, &val);
372 g_value_unset (&val);
384 paste_syntax_in_new_window (const gchar *syntax)
386 GtkWidget *se = psppire_syntax_window_new ();
388 gtk_text_buffer_insert_at_cursor (PSPPIRE_SYNTAX_WINDOW (se)->buffer, syntax, -1);
390 gtk_widget_show (se);