Remove awkward dependency from psppire-selector.c
[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   {
127     const char *filename = output_file_name ();
128
129     struct string config_string;
130
131     ds_init_empty (&config_string);
132
133     ds_put_format (&config_string,
134                    "gui:ascii:screen:squeeze=on headers=off top-margin=0 "
135                    "bottom-margin=0 paginate=off length=auto width=auto "
136                    "emphasis=none "
137                    "output-file=\"%s\" append=yes", filename);
138
139     outp_configure_driver_line (ds_ss (&config_string));
140
141     unlink (filename);
142
143     ds_destroy (&config_string);
144   }
145
146   journal_enable ();
147   textdomain (PACKAGE);
148
149
150   the_recent_mgr = gtk_recent_manager_get_default ();
151
152   psppire_selector_set_default_selection_func (GTK_TYPE_ENTRY, insert_source_row_into_entry);
153   psppire_selector_set_default_selection_func (PSPPIRE_VAR_VIEW_TYPE, insert_source_row_into_tree_view);
154   psppire_selector_set_default_selection_func (GTK_TYPE_TREE_VIEW, insert_source_row_into_tree_view);
155
156   the_data_window = psppire_data_window_new ();
157
158   command_line_processor_replace_aux (clp, &post_init_argp, the_source_stream);
159   command_line_processor_replace_aux (clp, &non_option_argp, the_source_stream);
160
161   command_line_processor_parse (clp, argc, argv);
162
163   execute_syntax (create_syntax_string_source (""));
164
165   gtk_widget_show (the_data_window);
166 }
167
168
169 void
170 de_initialize (void)
171 {
172   destroy_source_stream (the_source_stream);
173   message_dialog_done ();
174   settings_done ();
175   outp_done ();
176   i18n_done ();
177 }
178
179
180 static void
181 func (gpointer key, gpointer value, gpointer data)
182 {
183   gboolean rv;
184   PsppireWindow *window = PSPPIRE_WINDOW (value);
185
186   g_signal_emit_by_name (window, "delete-event", 0, &rv);
187 }
188
189 void
190 psppire_quit (void)
191 {
192   PsppireWindowRegister *reg = psppire_window_register_new ();
193   psppire_window_register_foreach (reg, func, NULL);
194
195   gtk_main_quit ();
196 }
197
198
199 struct icon_info
200 {
201   const char *file_name;
202   const gchar *id;
203 };
204
205
206 static const struct icon_info icons[] =
207   {
208     {PKGDATADIR "/value-labels.png",    "pspp-value-labels"},
209     {PKGDATADIR "/weight-cases.png",    "pspp-weight-cases"},
210     {PKGDATADIR "/goto-variable.png",   "pspp-goto-variable"},
211     {PKGDATADIR "/insert-variable.png", "pspp-insert-variable"},
212     {PKGDATADIR "/insert-case.png",     "pspp-insert-case"},
213     {PKGDATADIR "/split-file.png",      "pspp-split-file"},
214     {PKGDATADIR "/select-cases.png",    "pspp-select-cases"},
215     {PKGDATADIR "/recent-dialogs.png",  "pspp-recent-dialogs"},
216     {PKGDATADIR "/nominal.png",         "var-nominal"},
217     {PKGDATADIR "/ordinal.png",         "var-ordinal"},
218     {PKGDATADIR "/scale.png",           "var-scale"},
219     {PKGDATADIR "/string.png",          "var-string"},
220     {PKGDATADIR "/date-scale.png",      "var-date-scale"}
221   };
222
223 static void
224 create_icon_factory (void)
225 {
226   gint i;
227   GtkIconFactory *factory = gtk_icon_factory_new ();
228
229   for (i = 0 ; i < sizeof (icons) / sizeof(icons[0]); ++i)
230     {
231       GError *err = NULL;
232       GdkPixbuf *pixbuf =
233         gdk_pixbuf_new_from_file (relocate (icons[i].file_name), &err);
234
235       if ( pixbuf )
236         {
237           GtkIconSet *icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
238           g_object_unref (pixbuf);
239           gtk_icon_factory_add ( factory, icons[i].id, icon_set);
240         }
241       else
242         {
243           g_warning ("Cannot create icon: %s", err->message);
244           g_clear_error (&err);
245         }
246     }
247
248   {
249     /* Create our own "pspp-stock-reset" item, using the
250        GTK_STOCK_REFRESH icon set */
251
252     GtkStockItem items[] = {
253       {"pspp-stock-reset", N_("_Reset"), 0, 0, PACKAGE},
254       {"pspp-stock-select", N_("_Select"), 0, 0, PACKAGE}
255     };
256
257
258     gtk_stock_add (items, 2);
259     gtk_icon_factory_add (factory, "pspp-stock-reset",
260                           gtk_icon_factory_lookup_default (GTK_STOCK_REFRESH)
261                           );
262
263     gtk_icon_factory_add (factory, "pspp-stock-select",
264                           gtk_icon_factory_lookup_default (GTK_STOCK_INDEX)
265                           );
266   }
267
268   gtk_icon_factory_add_default (factory);
269 }
270
271 \f
272
273 static error_t
274 parse_non_options (int key, char *arg, struct argp_state *state)
275 {
276   struct source_stream *ss = state->input;
277
278   if ( NULL == ss )
279     return 0;
280
281   switch (key)
282     {
283     case ARGP_KEY_ARG:
284       {
285         gchar *filename = NULL;
286         gchar *utf8 = NULL;
287         const gchar *local_encoding = NULL;
288         gsize written = -1;
289         const gboolean local_is_utf8 = g_get_charset (&local_encoding);
290
291         /* There seems to be no Glib function to convert from local encoding
292            to filename encoding.  Therefore it has to be done in two steps:
293            the intermediate encoding is UTF8.
294
295            Either step could fail.  However, in many cases the file can still
296            be loaded even if the conversion fails. So in those cases, after showing
297            a warning, we simply copy the locally encoded filename to the destination
298            and hope for the best.
299         */
300
301         if ( local_is_utf8)
302           {
303             utf8 = xstrdup (arg);
304           }
305         else
306           {
307             GError *err = NULL;
308             utf8 = g_locale_to_utf8 (arg, -1, NULL, &written, &err);
309             if ( NULL == utf8)
310               {
311                 g_warning ("Cannot convert filename from local encoding \"%s\" to UTF-8: %s",
312                            local_encoding,
313                            err->message);
314                 g_clear_error (&err);
315               }
316           }
317
318         if ( NULL != utf8)
319           {
320             GError *err = NULL;
321             filename = g_filename_from_utf8 (utf8, written, NULL, NULL, &err);
322             if ( NULL == filename)
323               {
324                 g_warning ("Cannot convert filename from UTF8 to filename encoding: %s",
325                            err->message);
326                 g_clear_error (&err);
327               }
328           }
329
330         g_free (utf8);
331
332         if ( filename == NULL)
333           filename = xstrdup (arg);
334
335         psppire_window_load (PSPPIRE_WINDOW (the_data_window), filename);
336
337         g_free (filename);
338         break;
339       }
340     default:
341       return ARGP_ERR_UNKNOWN;
342     }
343   return 0;
344 }
345
346
347 const struct argp non_option_argp = {NULL, parse_non_options, 0, 0, 0, 0, 0};
348
349
350 const char *
351 output_file_name (void)
352 {
353   const char *dir = default_output_path ();
354   static char *filename = NULL;
355
356   if ( NULL == filename )
357     filename = xasprintf ("%s%s", dir, OUTPUT_FILE_NAME);
358
359   return filename;
360 }