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