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