Deleted psppire-case-file.[ch]
[pspp-builds.git] / src / ui / gui / helper.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007  Free Software Foundation
3
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.
8
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.
13
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/>. */
16
17
18 /* This file is a rubbish bin where stuff gets put when it doesn't seem to
19    belong anywhere else.
20 */
21 #include <config.h>
22
23 #include        <glib-object.h>
24
25 #include <glib.h>
26 #include "helper.h"
27 #include "message-dialog.h"
28 #include <data/format.h>
29 #include <data/data-in.h>
30 #include <data/data-out.h>
31 #include <data/dictionary.h>
32 #include <data/casereader-provider.h>
33 #include <libpspp/message.h>
34
35 #include <libpspp/i18n.h>
36
37 #include <ctype.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <data/settings.h>
41
42 #include <language/command.h>
43 #include <data/lazy-casereader.h>
44 #include <data/procedure.h>
45 #include <language/lexer/lexer.h>
46 #include "psppire-data-store.h"
47 #include <output/manager.h>
48 #include "output-viewer.h"
49
50 #include "xalloc.h"
51
52 #include <gettext.h>
53
54 /* Formats a value according to FORMAT
55    The returned string must be freed when no longer required */
56 gchar *
57 value_to_text (union value v, struct fmt_spec format)
58 {
59   gchar *s = 0;
60
61   s = g_new (gchar, format.w + 1);
62   data_out (&v, &format, s);
63   s[format.w]='\0';
64   g_strchug (s);
65
66   return s;
67 }
68
69
70
71 gboolean
72 text_to_value (const gchar *text, union value *v,
73               struct fmt_spec format)
74 {
75   bool ok;
76
77   if ( format.type != FMT_A)
78     {
79       if ( ! text ) return FALSE;
80
81       {
82         const gchar *s = text;
83         while (*s)
84           {
85             if ( !isspace (*s))
86               break;
87             s++;
88           }
89
90         if ( !*s) return FALSE;
91       }
92     }
93
94   msg_disable ();
95   ok = data_in (ss_cstr (text), LEGACY_NATIVE, format.type, 0, 0, 0,
96                 v, fmt_var_width (&format));
97   msg_enable ();
98
99   return ok;
100 }
101
102
103 GtkWidget *
104 get_widget_assert (GladeXML *xml, const gchar *name)
105 {
106   GtkWidget *w;
107   g_assert (xml);
108   g_assert (name);
109
110   w = glade_xml_get_widget (xml, name);
111
112   if ( !w )
113     g_critical ("Widget \"%s\" could not be found\n", name);
114
115   return w;
116 }
117
118 /* Converts a string in the pspp locale to utf-8.
119    The return value must be freed when no longer required*/
120 gchar *
121 pspp_locale_to_utf8 (const gchar *text, gssize len, GError **err)
122 {
123   return recode_string (CONV_PSPP_TO_UTF8, text, len);
124 }
125
126 #define _(msgid) gettext (msgid)
127 #define N_(msgid) msgid
128
129
130 static void
131 give_help (void)
132 {
133   GtkWidget *dialog;
134
135   dialog = gtk_message_dialog_new (NULL,
136                                    GTK_DIALOG_MODAL,
137                                    GTK_MESSAGE_INFO,
138                                    GTK_BUTTONS_CLOSE,
139                                    _("Sorry. The help system hasn't yet "
140                                      "been implemented."));
141   gtk_dialog_run (GTK_DIALOG (dialog));
142   gtk_widget_destroy (dialog);
143 }
144
145 void
146 connect_help (GladeXML *xml)
147 {
148   GList *helps = glade_xml_get_widget_prefix (xml, "help_button_");
149
150   GList *i;
151   for ( i = g_list_first (helps); i ; i = g_list_next (i))
152     g_signal_connect (GTK_WIDGET (i->data), "clicked", give_help, 0);
153
154   g_list_free (helps);
155 }
156
157
158
159 void
160 reference_manual (GtkMenuItem *menu, gpointer data)
161 {
162   GError *err = NULL;
163   if ( ! g_spawn_command_line_async ("yelp info:pspp", &err) )
164     {
165       msg (ME, _("Cannot open reference manual: %s"), err->message);
166     }
167   g_clear_error (&err);
168 }
169
170
171 extern struct dataset *the_dataset;
172 extern struct source_stream *the_source_stream;
173 extern PsppireDataStore *the_data_store;
174
175 /* Lazy casereader callback function used by execute_syntax. */
176 static struct casereader *
177 create_casereader_from_data_store (void *data_store_)
178 {
179   PsppireDataStore *data_store = data_store_;
180   return psppire_data_store_get_reader (data_store);
181 }
182
183 gboolean
184 execute_syntax (struct getl_interface *sss)
185 {
186   struct lexer *lexer;
187   gboolean retval = TRUE;
188
189   struct casereader *reader;
190   size_t value_cnt;
191   casenumber case_cnt;
192   unsigned long int lazy_serial;
193
194   /* When the user executes a number of snippets of syntax in a
195      row, none of which read from the active file, the GUI becomes
196      progressively less responsive.  The reason is that each syntax
197      execution encapsulates the active file data in another
198      datasheet layer.  The cumulative effect of having a number of
199      layers of datasheets wastes time and space.
200
201      To solve the problem, we use a "lazy casereader", a wrapper
202      around the casereader obtained from the data store, that
203      only actually instantiates that casereader when it is
204      needed.  If the data store casereader is never needed, then
205      it is reused the next time syntax is run, without wrapping
206      it in another layer. */
207   value_cnt = psppire_data_store_get_value_count (the_data_store);
208   case_cnt = psppire_data_store_get_case_count (the_data_store);
209   reader = lazy_casereader_create (value_cnt, case_cnt,
210                                    create_casereader_from_data_store,
211                                    the_data_store, &lazy_serial);
212   proc_set_active_file_data (the_dataset, reader);
213
214   g_return_val_if_fail (proc_has_active_file (the_dataset), FALSE);
215
216   lexer = lex_create (the_source_stream);
217
218   getl_append_source (the_source_stream, sss, GETL_BATCH, ERRMODE_CONTINUE);
219
220   for (;;)
221     {
222       enum cmd_result result = cmd_parse (lexer, the_dataset);
223
224       if ( cmd_result_is_failure (result))
225         {
226           retval = FALSE;
227           if ( source_stream_current_error_mode (the_source_stream)
228                == ERRMODE_STOP )
229             break;
230         }
231
232       if ( result == CMD_EOF || result == CMD_FINISH)
233         break;
234     }
235
236   getl_abort_noninteractive (the_source_stream);
237
238   lex_destroy (lexer);
239
240   psppire_dict_replace_dictionary (the_data_store->dict,
241                                    dataset_dict (the_dataset));
242
243   reader = proc_extract_active_file_data (the_dataset);
244   if (!lazy_casereader_destroy (reader, lazy_serial))
245     psppire_data_store_set_reader (the_data_store, reader);
246
247   som_flush ();
248
249   reload_the_viewer ();
250
251   return retval;
252 }
253
254
255
256 /* Create a deep copy of SRC */
257 GtkListStore *
258 clone_list_store (const GtkListStore *src)
259 {
260   GtkTreeIter src_iter;
261   gboolean ok;
262   gint i;
263   const gint n_cols =  gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
264   GType *types = g_malloc (sizeof (*types) *  n_cols);
265
266   int row = 0;
267   GtkListStore *dest;
268
269   for (i = 0 ; i < n_cols; ++i )
270     types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
271
272   dest = gtk_list_store_newv (n_cols, types);
273
274   for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
275                                            &src_iter);
276        ok;
277        ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
278     {
279       GtkTreeIter dest_iter;
280       gtk_list_store_append  (dest, &dest_iter);
281
282       for (i = 0 ; i < n_cols; ++i )
283         {
284           GValue val = {0};
285
286           gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
287           gtk_list_store_set_value (dest, &dest_iter, i, &val);
288
289           g_value_unset (&val);
290         }
291       row++;
292     }
293
294   g_free (types);
295
296   return dest;
297 }
298
299