Rename procedure.[ch] to dataset.[ch].
[pspp-builds.git] / src / ui / gui / psppire.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2004, 2005, 2006, 2009, 2010  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 #include <config.h>
18
19 #include <assert.h>
20 #include <gsl/gsl_errno.h>
21 #include <gtk/gtk.h>
22 #include <libintl.h>
23 #include <unistd.h>
24
25 #include "data/casereader.h"
26 #include "data/dataset.h"
27 #include "data/datasheet.h"
28 #include "data/file-handle-def.h"
29 #include "data/file-name.h"
30 #include "data/por-file-reader.h"
31 #include "data/settings.h"
32 #include "data/sys-file-reader.h"
33
34 #include "language/lexer/lexer.h"
35 #include "libpspp/i18n.h"
36 #include "libpspp/message.h"
37 #include "libpspp/version.h"
38
39 #include "output/driver.h"
40 #include "output/journal.h"
41 #include "output/message-item.h"
42
43 #include "ui/gui/dict-display.h"
44 #include "ui/gui/executor.h"
45 #include "ui/gui/psppire-data-store.h"
46 #include "ui/gui/psppire-data-window.h"
47 #include "ui/gui/psppire-dict.h"
48 #include "ui/gui/psppire-output-window.h"
49 #include "ui/gui/psppire-selector.h"
50 #include "ui/gui/psppire-var-store.h"
51 #include "ui/gui/psppire-var-view.h"
52 #include "ui/gui/psppire-window-register.h"
53 #include "ui/gui/psppire.h"
54 #include "ui/gui/widgets.h"
55 #include "ui/source-init-opts.h"
56 #include "ui/syntax-gen.h"
57
58 #include "gl/configmake.h"
59 #include "gl/xalloc.h"
60 #include "gl/relocatable.h"
61
62 GtkRecentManager *the_recent_mgr = 0;
63 PsppireDataStore *the_data_store = 0;
64 PsppireVarStore *the_var_store = 0;
65
66 static void create_icon_factory (void);
67
68 struct dataset * the_dataset = NULL;
69
70 static GtkWidget *the_data_window;
71
72 static void load_data_file (const char *);
73
74 static void
75 replace_casereader (struct casereader *s)
76 {
77   psppire_data_store_set_reader (the_data_store, s);
78 }
79
80 #define _(msgid) gettext (msgid)
81 #define N_(msgid) msgid
82
83
84
85
86 void
87 initialize (const char *data_file)
88 {
89   PsppireDict *dictionary = 0;
90
91   i18n_init ();
92
93   preregister_widgets ();
94
95   gsl_set_error_handler_off ();
96   settings_init ();
97   fh_init ();
98
99   the_dataset = create_dataset ();
100   psppire_set_lexer (NULL);
101
102   dictionary = psppire_dict_new_from_dict (dataset_dict (the_dataset));
103
104   bind_textdomain_codeset (PACKAGE, "UTF-8");
105
106   /* Create the model for the var_sheet */
107   the_var_store = psppire_var_store_new (dictionary);
108
109   the_data_store = psppire_data_store_new (dictionary);
110   replace_casereader (NULL);
111
112   create_icon_factory ();
113
114   psppire_output_window_setup ();
115
116   journal_enable ();
117   textdomain (PACKAGE);
118
119
120   the_recent_mgr = gtk_recent_manager_get_default ();
121
122   psppire_selector_set_default_selection_func (GTK_TYPE_ENTRY, insert_source_row_into_entry);
123   psppire_selector_set_default_selection_func (PSPPIRE_VAR_VIEW_TYPE, insert_source_row_into_tree_view);
124   psppire_selector_set_default_selection_func (GTK_TYPE_TREE_VIEW, insert_source_row_into_tree_view);
125
126   the_data_window = psppire_data_window_new ();
127   if (data_file != NULL)
128     load_data_file (data_file);
129
130   execute_const_syntax_string ("");
131
132   gtk_widget_show (the_data_window);
133 }
134
135
136 void
137 de_initialize (void)
138 {
139   settings_done ();
140   output_close ();
141   i18n_done ();
142 }
143
144
145 static void
146 func (gpointer key, gpointer value, gpointer data)
147 {
148   gboolean rv;
149   PsppireWindow *window = PSPPIRE_WINDOW (value);
150
151   g_signal_emit_by_name (window, "delete-event", 0, &rv);
152 }
153
154 void
155 psppire_quit (void)
156 {
157   PsppireWindowRegister *reg = psppire_window_register_new ();
158   psppire_window_register_foreach (reg, func, NULL);
159
160   gtk_main_quit ();
161 }
162
163
164 struct icon_info
165 {
166   const char *file_name;
167   const gchar *id;
168 };
169
170
171 static const struct icon_info icons[] =
172   {
173     {PKGDATADIR "/value-labels.png",    "pspp-value-labels"},
174     {PKGDATADIR "/weight-cases.png",    "pspp-weight-cases"},
175     {PKGDATADIR "/goto-variable.png",   "pspp-goto-variable"},
176     {PKGDATADIR "/insert-variable.png", "pspp-insert-variable"},
177     {PKGDATADIR "/insert-case.png",     "pspp-insert-case"},
178     {PKGDATADIR "/split-file.png",      "pspp-split-file"},
179     {PKGDATADIR "/select-cases.png",    "pspp-select-cases"},
180     {PKGDATADIR "/recent-dialogs.png",  "pspp-recent-dialogs"},
181     {PKGDATADIR "/nominal.png",         "var-nominal"},
182     {PKGDATADIR "/ordinal.png",         "var-ordinal"},
183     {PKGDATADIR "/scale.png",           "var-scale"},
184     {PKGDATADIR "/string.png",          "var-string"},
185     {PKGDATADIR "/date-scale.png",      "var-date-scale"}
186   };
187
188 static void
189 create_icon_factory (void)
190 {
191   gint i;
192   GtkIconFactory *factory = gtk_icon_factory_new ();
193
194   for (i = 0 ; i < sizeof (icons) / sizeof(icons[0]); ++i)
195     {
196       GError *err = NULL;
197       GdkPixbuf *pixbuf =
198         gdk_pixbuf_new_from_file (relocate (icons[i].file_name), &err);
199
200       if ( pixbuf )
201         {
202           GtkIconSet *icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
203           g_object_unref (pixbuf);
204           gtk_icon_factory_add ( factory, icons[i].id, icon_set);
205         }
206       else
207         {
208           g_warning ("Cannot create icon: %s", err->message);
209           g_clear_error (&err);
210         }
211     }
212
213   {
214     /* Create our own "pspp-stock-reset" item, using the
215        GTK_STOCK_REFRESH icon set */
216
217     GtkStockItem items[] = {
218       {"pspp-stock-reset", N_("_Reset"), 0, 0, PACKAGE},
219       {"pspp-stock-select", N_("_Select"), 0, 0, PACKAGE}
220     };
221
222
223     gtk_stock_add (items, 2);
224     gtk_icon_factory_add (factory, "pspp-stock-reset",
225                           gtk_icon_factory_lookup_default (GTK_STOCK_REFRESH)
226                           );
227
228     gtk_icon_factory_add (factory, "pspp-stock-select",
229                           gtk_icon_factory_lookup_default (GTK_STOCK_INDEX)
230                           );
231   }
232
233   gtk_icon_factory_add_default (factory);
234 }
235 \f
236 static void
237 load_data_file (const char *arg)
238 {
239   gchar *filename = NULL;
240   gchar *utf8 = NULL;
241   const gchar *local_encoding = NULL;
242   gsize written = -1;
243   const gboolean local_is_utf8 = g_get_charset (&local_encoding);
244
245   /* There seems to be no Glib function to convert from local encoding
246      to filename encoding.  Therefore it has to be done in two steps:
247      the intermediate encoding is UTF8.
248
249      Either step could fail.  However, in many cases the file can still
250      be loaded even if the conversion fails. So in those cases, after showing
251      a warning, we simply copy the locally encoded filename to the destination
252      and hope for the best.
253   */
254
255   if ( local_is_utf8)
256     {
257       utf8 = xstrdup (arg);
258     }
259   else
260     {
261       GError *err = NULL;
262       utf8 = g_locale_to_utf8 (arg, -1, NULL, &written, &err);
263       if ( NULL == utf8)
264         {
265           g_warning ("Cannot convert filename from local encoding `%s' to UTF-8: %s",
266                      local_encoding,
267                      err->message);
268           g_clear_error (&err);
269         }
270     }
271
272   if ( NULL != utf8)
273     {
274       GError *err = NULL;
275       filename = g_filename_from_utf8 (utf8, written, NULL, NULL, &err);
276       if ( NULL == filename)
277         {
278           g_warning ("Cannot convert filename from UTF8 to filename encoding: %s",
279                      err->message);
280           g_clear_error (&err);
281         }
282     }
283
284   g_free (utf8);
285
286   if ( filename == NULL)
287     filename = xstrdup (arg);
288
289   psppire_window_load (PSPPIRE_WINDOW (the_data_window), filename);
290
291   g_free (filename);
292 }
293
294 static void
295 handle_msg (const struct msg *m_, void *lexer_)
296 {
297   struct lexer *lexer = lexer_;
298   struct msg m = *m_;
299
300   if (lexer != NULL && m.file_name == NULL)
301     {
302       m.file_name = CONST_CAST (char *, lex_get_file_name (lexer));
303       m.first_line = lex_get_first_line_number (lexer, 0);
304       m.last_line = lex_get_last_line_number (lexer, 0);
305       m.first_column = lex_get_first_column (lexer, 0);
306       m.last_column = lex_get_last_column (lexer, 0);
307     }
308
309   message_item_submit (message_item_create (&m));
310 }
311
312 void
313 psppire_set_lexer (struct lexer *lexer)
314 {
315   msg_set_handler (handle_msg, lexer);
316 }