gui: Drop 'dict' parameter from text_to_value().
[pspp-builds.git] / src / ui / gui / helper.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007, 2009, 2010, 2011  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 <data/format.h>
28 #include <data/data-in.h>
29 #include <data/data-out.h>
30 #include <data/dictionary.h>
31 #include <data/casereader-provider.h>
32 #include <libpspp/message.h>
33 #include "psppire-syntax-window.h"
34 #include <gtk/gtk.h>
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 "psppire-data-store.h"
43 #include "psppire.h"
44
45 #include "gl/configmake.h"
46 #include "xalloc.h"
47
48 #include <gettext.h>
49
50 /* Formats a value according to FORMAT
51    The returned string must be freed when no longer required */
52 gchar *
53 value_to_text (union value v, const PsppireDict *dict, struct fmt_spec format)
54 {
55   gchar *s = NULL;
56
57   s = data_out (&v, dict_get_encoding (dict->dict),  &format);
58   g_strchug (s);
59
60   return s;
61 }
62
63
64 /* Converts TEXT to a value.
65
66    VAL will be initialised and filled by this function.
67    It is the caller's responsibility to destroy VAL when no longer needed.
68    VAR must be the variable with which VAL is associated.
69
70    On success, VAL is returned, NULL otherwise.
71 */
72 union value *
73 text_to_value (const gchar *text,
74                const struct variable *var,
75                union value *val)
76 {
77   const struct fmt_spec *format = var_get_print_format (var);
78   int width = var_get_width (var);
79
80   if ( format->type != FMT_A)
81     {
82       if ( ! text ) return NULL;
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 NULL;
94       }
95     }
96
97   value_init (val, width);
98   free (data_in (ss_cstr (text), UTF8, format->type, val, width,
99                  var_get_encoding (var)));
100
101   return val;
102 }
103
104
105 GtkBuilder *
106 builder_new_real (const gchar *name)
107 {
108   GtkBuilder *builder = gtk_builder_new ();
109
110   GError *err = NULL;
111   if ( ! gtk_builder_add_from_file (builder, name,  &err))
112     {
113       g_critical ("Couldnt open user interface  file %s: %s", name, err->message);
114       g_clear_error (&err);
115     }
116
117   return builder;
118 }
119
120
121 GObject *
122 get_object_assert (GtkBuilder *builder, const gchar *name, GType type)
123 {
124   GObject *o = NULL;
125   g_assert (name);
126
127   o = gtk_builder_get_object (builder, name);
128
129   if ( !o )
130     g_critical ("Object `%s' could not be found\n", name);
131   else if ( ! g_type_is_a (G_OBJECT_TYPE (o), type))
132    {
133      g_critical ("Object `%s' was expected to have type %s, but in fact has type %s", 
134         name, g_type_name (type), G_OBJECT_TYPE_NAME (o));
135    }
136
137   return o;
138 }
139
140
141 GtkAction *
142 get_action_assert (GtkBuilder *builder, const gchar *name)
143 {
144   return GTK_ACTION (get_object_assert (builder, name, GTK_TYPE_ACTION));
145 }
146
147 GtkWidget *
148 get_widget_assert (GtkBuilder *builder, const gchar *name)
149 {
150   return GTK_WIDGET (get_object_assert (builder, name, GTK_TYPE_WIDGET));
151 }
152
153 /* This function must be used whenever a filename generated by glib,
154    (eg, from gtk_file_chooser_get_filename) and passed to the C library,
155    (eg through a pspp syntax string).
156 */
157 gchar *
158 convert_glib_filename_to_system_filename (const gchar *fname, GError **err)
159 {
160   gchar *output_name;
161
162 #ifdef G_OS_WIN32
163   const gchar *target_encoding;
164   gchar *utf8_name = NULL;
165
166   g_get_charset (&target_encoding);
167
168   output_name = g_convert (fname, -1, target_encoding,
169                         "UTF-8", NULL, NULL, err);
170 #else
171   output_name = xstrdup (fname);
172 #endif
173
174   return output_name;
175 }
176
177
178
179 #define _(msgid) gettext (msgid)
180 #define N_(msgid) msgid
181
182
183 static void
184 give_help (void)
185 {
186   GtkWidget *dialog;
187
188   dialog = gtk_message_dialog_new (NULL,
189                                    GTK_DIALOG_MODAL,
190                                    GTK_MESSAGE_INFO,
191                                    GTK_BUTTONS_CLOSE,
192                                    _("Sorry. The help system hasn't yet "
193                                      "been implemented."));
194   gtk_dialog_run (GTK_DIALOG (dialog));
195   gtk_widget_destroy (dialog);
196 }
197
198 void
199 connect_help (GtkBuilder *xml)
200 {
201   GSList *helps = gtk_builder_get_objects (xml);
202
203   GSList *i;
204   for ( i = helps; i ; i = g_slist_next (i))
205     {
206       GObject *o = i->data;
207       if ( GTK_IS_WIDGET (o) )
208         {
209           const gchar *name = gtk_buildable_get_name (GTK_BUILDABLE (o));
210           gchar s[12] = {0};
211
212           if ( name)
213             strncpy (s, name, 11);
214           s[11] = '\0';
215
216
217           if ( 0 == strcmp ("help_button", s))
218             {
219             g_signal_connect (o, "clicked", give_help, 0);
220             }
221         }
222     }
223
224   g_slist_free (helps);
225 }
226
227
228 /* Create a deep copy of SRC */
229 GtkListStore *
230 clone_list_store (const GtkListStore *src)
231 {
232   GtkTreeIter src_iter;
233   gboolean ok;
234   gint i;
235   const gint n_cols =  gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
236   GType *types = g_malloc (sizeof (*types) *  n_cols);
237
238   int row = 0;
239   GtkListStore *dest;
240
241   for (i = 0 ; i < n_cols; ++i )
242     types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
243
244   dest = gtk_list_store_newv (n_cols, types);
245
246   for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
247                                            &src_iter);
248        ok;
249        ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
250     {
251       GtkTreeIter dest_iter;
252       gtk_list_store_append  (dest, &dest_iter);
253
254       for (i = 0 ; i < n_cols; ++i )
255         {
256           GValue val = {0};
257
258           gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
259           gtk_list_store_set_value (dest, &dest_iter, i, &val);
260
261           g_value_unset (&val);
262         }
263       row++;
264     }
265
266   g_free (types);
267
268   return dest;
269 }
270
271
272
273
274 static gboolean 
275 on_delete (GtkWindow *window, GdkEvent *e, GtkWindow **addr)
276 {
277   *addr = NULL;
278
279   return FALSE;
280 }
281
282 char *
283 paste_syntax_to_window (gchar *syntax)
284 {
285   static GtkWidget *the_syntax_pasteboard = NULL;
286
287   GtkTextBuffer *buffer = NULL;
288
289   if ( NULL == the_syntax_pasteboard)
290     {
291       the_syntax_pasteboard = psppire_syntax_window_new (NULL);
292       g_signal_connect (the_syntax_pasteboard, "delete-event", G_CALLBACK (on_delete),
293                         &the_syntax_pasteboard);
294     }
295
296   buffer = GTK_TEXT_BUFFER (PSPPIRE_SYNTAX_WINDOW (the_syntax_pasteboard)->buffer);
297
298   gtk_text_buffer_begin_user_action (buffer);
299   gtk_text_buffer_insert_at_cursor (buffer, syntax, -1);
300   gtk_text_buffer_insert_at_cursor (buffer, "\n", 1);
301   gtk_text_buffer_end_user_action (buffer);
302
303   gtk_widget_show (the_syntax_pasteboard);
304
305   return syntax;
306 }
307
308
309 /* gtk_box_pack_start_defaults is deprecated.
310    Therefore we roll our own until a better solution is found */
311 void
312 psppire_box_pack_start_defaults (GtkBox *box, GtkWidget *widget)
313 {
314   gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
315 }