Remove glade version of connect_help
[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 "psppire-syntax-window.h"
24
25 #include        <glib-object.h>
26
27 #include <glib.h>
28 #include "helper.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>
36
37 #include <gtk/gtkbuilder.h>
38 #include <libpspp/i18n.h>
39
40 #include <ctype.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <data/settings.h>
44
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"
52
53 #include "xalloc.h"
54
55 #include <gettext.h>
56
57 /* Formats a value according to FORMAT
58    The returned string must be freed when no longer required */
59 gchar *
60 value_to_text (union value v, struct fmt_spec format)
61 {
62   gchar *s = 0;
63
64   s = g_new (gchar, format.w + 1);
65   data_out (&v, &format, s);
66   s[format.w]='\0';
67   g_strchug (s);
68
69   return s;
70 }
71
72
73
74 gboolean
75 text_to_value (const gchar *text, union value *v,
76               struct fmt_spec format)
77 {
78   bool ok;
79
80   if ( format.type != FMT_A)
81     {
82       if ( ! text ) return FALSE;
83
84       {
85         const gchar *s = text;
86         while (*s)
87           {
88             if ( !isspace (*s))
89               break;
90             s++;
91           }
92
93         if ( !*s) return FALSE;
94       }
95     }
96
97   msg_disable ();
98   ok = data_in (ss_cstr (text), LEGACY_NATIVE, format.type, 0, 0, 0,
99                 v, fmt_var_width (&format));
100   msg_enable ();
101
102   return ok;
103 }
104
105
106 GtkBuilder *
107 builder_new_real (const gchar *name)
108 {
109   GtkBuilder *builder = gtk_builder_new ();
110
111   GError *err = NULL;
112   if ( ! gtk_builder_add_from_file (builder, name,  &err))
113     {
114       g_critical ("Couldnt open user interface  file %s: %s", name, err->message);
115       g_clear_error (&err);
116     }
117
118   return builder;
119 }
120
121
122 GObject *
123 get_object_assert (GtkBuilder *builder, const gchar *name)
124 {
125   GObject *o = NULL;
126   g_assert (name);
127
128   o = gtk_builder_get_object (builder, name);
129
130   if ( !o )
131     g_critical ("Object \"%s\" could not be found\n", name);
132
133   return o;
134 }
135
136 GtkWidget *
137 get_widget_assert (gpointer x, const gchar *name)
138 {
139   GObject *obj = G_OBJECT (x);
140   GtkWidget *w = NULL;
141   g_assert (name);
142
143   if (GTK_IS_BUILDER (obj))
144     w = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (obj), name));
145
146   if (GLADE_IS_XML (obj))
147     w = glade_xml_get_widget (GLADE_XML (obj), name);
148
149   if ( !w )
150     g_critical ("Widget \"%s\" could not be found\n", name);
151
152   return w;
153 }
154
155 /* Converts a string in the pspp locale to utf-8.
156    The return value must be freed when no longer required*/
157 gchar *
158 pspp_locale_to_utf8 (const gchar *text, gssize len, GError **err)
159 {
160   return recode_string (CONV_PSPP_TO_UTF8, text, len);
161 }
162
163 #define _(msgid) gettext (msgid)
164 #define N_(msgid) msgid
165
166
167 static void
168 give_help (void)
169 {
170   GtkWidget *dialog;
171
172   dialog = gtk_message_dialog_new (NULL,
173                                    GTK_DIALOG_MODAL,
174                                    GTK_MESSAGE_INFO,
175                                    GTK_BUTTONS_CLOSE,
176                                    _("Sorry. The help system hasn't yet "
177                                      "been implemented."));
178   gtk_dialog_run (GTK_DIALOG (dialog));
179   gtk_widget_destroy (dialog);
180 }
181
182 void
183 connect_help (GtkBuilder *xml)
184 {
185   GSList *helps = gtk_builder_get_objects (xml);
186
187   GSList *i;
188   for ( i = helps; i ; i = g_slist_next (i))
189     {
190       GObject *o = i->data;
191       if ( GTK_IS_WIDGET (o) )
192         {
193           gchar *name = NULL;
194           gchar s[12] = {0};
195           g_object_get (o, "name", &name, NULL);
196
197           if ( name)
198             strncpy (s, name, 11);
199           s[11] = '\0';
200
201
202           if ( 0 == strcmp ("help_button", s))
203             {
204             g_signal_connect (GTK_WIDGET (o), "clicked", give_help, 0);
205             }
206         }
207     }
208
209   g_slist_free (helps);
210 }
211
212
213 void
214 reference_manual (GtkMenuItem *menu, gpointer data)
215 {
216   GError *err = NULL;
217   if ( ! g_spawn_command_line_async ("yelp info:pspp", &err) )
218     {
219       msg (ME, _("Cannot open reference manual: %s"), err->message);
220     }
221   g_clear_error (&err);
222 }
223
224
225 extern struct dataset *the_dataset;
226 extern struct source_stream *the_source_stream;
227 extern PsppireDataStore *the_data_store;
228
229 /* Lazy casereader callback function used by execute_syntax. */
230 static struct casereader *
231 create_casereader_from_data_store (void *data_store_)
232 {
233   PsppireDataStore *data_store = data_store_;
234   return psppire_data_store_get_reader (data_store);
235 }
236
237 gboolean
238 execute_syntax (struct getl_interface *sss)
239 {
240   struct lexer *lexer;
241   gboolean retval = TRUE;
242
243   struct casereader *reader;
244   size_t value_cnt;
245   casenumber case_cnt;
246   unsigned long int lazy_serial;
247
248   /* When the user executes a number of snippets of syntax in a
249      row, none of which read from the active file, the GUI becomes
250      progressively less responsive.  The reason is that each syntax
251      execution encapsulates the active file data in another
252      datasheet layer.  The cumulative effect of having a number of
253      layers of datasheets wastes time and space.
254
255      To solve the problem, we use a "lazy casereader", a wrapper
256      around the casereader obtained from the data store, that
257      only actually instantiates that casereader when it is
258      needed.  If the data store casereader is never needed, then
259      it is reused the next time syntax is run, without wrapping
260      it in another layer. */
261   value_cnt = psppire_data_store_get_value_count (the_data_store);
262   case_cnt = psppire_data_store_get_case_count (the_data_store);
263   reader = lazy_casereader_create (value_cnt, case_cnt,
264                                    create_casereader_from_data_store,
265                                    the_data_store, &lazy_serial);
266   proc_set_active_file_data (the_dataset, reader);
267
268   g_return_val_if_fail (proc_has_active_file (the_dataset), FALSE);
269
270   lexer = lex_create (the_source_stream);
271
272   getl_append_source (the_source_stream, sss, GETL_BATCH, ERRMODE_CONTINUE);
273
274   for (;;)
275     {
276       enum cmd_result result = cmd_parse (lexer, the_dataset);
277
278       if ( cmd_result_is_failure (result))
279         {
280           retval = FALSE;
281           if ( source_stream_current_error_mode (the_source_stream)
282                == ERRMODE_STOP )
283             break;
284         }
285
286       if ( result == CMD_EOF || result == CMD_FINISH)
287         break;
288     }
289
290   getl_abort_noninteractive (the_source_stream);
291
292   lex_destroy (lexer);
293
294   psppire_dict_replace_dictionary (the_data_store->dict,
295                                    dataset_dict (the_dataset));
296
297   reader = proc_extract_active_file_data (the_dataset);
298   if (!lazy_casereader_destroy (reader, lazy_serial))
299     psppire_data_store_set_reader (the_data_store, reader);
300
301   som_flush ();
302
303   psppire_output_window_reload ();
304
305   return retval;
306 }
307
308
309
310 /* Create a deep copy of SRC */
311 GtkListStore *
312 clone_list_store (const GtkListStore *src)
313 {
314   GtkTreeIter src_iter;
315   gboolean ok;
316   gint i;
317   const gint n_cols =  gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
318   GType *types = g_malloc (sizeof (*types) *  n_cols);
319
320   int row = 0;
321   GtkListStore *dest;
322
323   for (i = 0 ; i < n_cols; ++i )
324     types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
325
326   dest = gtk_list_store_newv (n_cols, types);
327
328   for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
329                                            &src_iter);
330        ok;
331        ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
332     {
333       GtkTreeIter dest_iter;
334       gtk_list_store_append  (dest, &dest_iter);
335
336       for (i = 0 ; i < n_cols; ++i )
337         {
338           GValue val = {0};
339
340           gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
341           gtk_list_store_set_value (dest, &dest_iter, i, &val);
342
343           g_value_unset (&val);
344         }
345       row++;
346     }
347
348   g_free (types);
349
350   return dest;
351 }
352
353
354 void
355 paste_syntax_in_new_window (const gchar *syntax)
356 {
357   GtkWidget *se = psppire_syntax_window_new ();
358
359   gtk_text_buffer_insert_at_cursor (PSPPIRE_SYNTAX_WINDOW (se)->buffer, syntax, -1);
360
361   gtk_widget_show (se);
362 }