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