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