1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation
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.
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.
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/>. */
19 #include "ui/gui/executor.h"
21 #include "data/dataset.h"
22 #include "data/lazy-casereader.h"
23 #include "data/session.h"
24 #include "language/command.h"
25 #include "language/lexer/lexer.h"
26 #include "libpspp/cast.h"
27 #include "output/driver.h"
28 #include "ui/gui/psppire-data-store.h"
29 #include "ui/gui/psppire.h"
31 /* Lazy casereader callback function used by execute_syntax. */
32 static struct casereader *
33 create_casereader_from_data_store (void *data_store_)
35 PsppireDataStore *data_store = data_store_;
36 return psppire_data_store_get_reader (data_store);
39 /* Ensures that dataset DS has a name, because some parts of the GUI insist
42 name_dataset_cb (struct dataset *ds, void *aux UNUSED)
44 if (dataset_name (ds)[0] == '\0')
46 struct session *session = dataset_session (ds);
47 char *dataset_name = session_generate_dataset_name (session);
48 dataset_set_name (ds, dataset_name);
54 new_pdw_cb (struct dataset *ds, void *aux UNUSED)
56 PsppireDataWindow *pdw = psppire_data_window_for_dataset (ds);
58 pdw = PSPPIRE_DATA_WINDOW (psppire_data_window_new (ds));
60 switch (dataset_get_display (ds))
66 gtk_widget_show (GTK_WIDGET (pdw));
67 gtk_window_deiconify (GTK_WINDOW (pdw));
68 gdk_window_raise (gtk_widget_get_window (GTK_WIDGET (pdw)));
69 psppire_data_window_set_default (pdw);
72 case DATASET_MINIMIZED:
73 gtk_window_iconify (GTK_WINDOW (pdw));
74 gtk_widget_show (GTK_WIDGET (pdw));
75 psppire_data_window_undefault (pdw);
79 gtk_widget_hide (GTK_WIDGET (pdw));
80 psppire_data_window_undefault (pdw);
83 dataset_set_display (ds, DATASET_ASIS);
87 execute_syntax (PsppireDataWindow *window, struct lex_reader *lex_reader)
90 gboolean retval = TRUE;
92 PsppireDataWindow *pdw, *next_pdw;
94 ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
96 const struct caseproto *proto;
97 struct casereader *reader;
100 /* When the user executes a number of snippets of syntax in a
101 row, none of which read from the active dataset, the GUI becomes
102 progressively less responsive. The reason is that each syntax
103 execution encapsulates the active dataset data in another
104 datasheet layer. The cumulative effect of having a number of
105 layers of datasheets wastes time and space.
107 To solve the problem, we use a "lazy casereader", a wrapper
108 around the casereader obtained from the data store, that
109 only actually instantiates that casereader when it is
110 needed. If the data store casereader is never needed, then
111 it is reused the next time syntax is run, without wrapping
112 it in another layer. */
113 proto = psppire_data_store_get_proto (pdw->data_store);
114 case_cnt = psppire_data_store_get_case_count (pdw->data_store);
115 reader = lazy_casereader_create (proto, case_cnt,
116 create_casereader_from_data_store,
117 pdw->data_store, &pdw->lazy_serial);
118 dataset_set_source (pdw->dataset, reader);
121 session_set_active_dataset (the_session, pdw->dataset);
123 g_return_val_if_fail (dataset_has_source (pdw->dataset), FALSE);
125 pdw->dataset_seqno = dataset_seqno (pdw->dataset);
128 lexer = lex_create ();
129 psppire_set_lexer (lexer);
130 lex_append (lexer, lex_reader);
134 struct dataset *ds = session_active_dataset (the_session);
135 enum cmd_result result = cmd_parse (lexer, ds);
137 if ( cmd_result_is_failure (result))
140 if ( lex_get_error_mode (lexer) == LEX_ERROR_STOP )
144 if ( result == CMD_EOF || result == CMD_FINISH)
148 session_for_each_dataset (the_session, name_dataset_cb, NULL);
150 ll_for_each_safe (pdw, next_pdw, PsppireDataWindow, ll, &all_data_windows)
154 ds = session_get_dataset_by_seqno (the_session, pdw->dataset_seqno);
157 struct casereader *reader;
160 proc_execute (pdw->dataset);
162 psppire_dict_replace_dictionary (pdw->data_store->dict,
163 dataset_dict (pdw->dataset));
165 reader = dataset_steal_source (pdw->dataset);
166 if (!lazy_casereader_destroy (reader, pdw->lazy_serial))
167 psppire_data_store_set_reader (pdw->data_store, reader);
169 g_object_set (G_OBJECT (pdw), "id", dataset_name (pdw->dataset),
173 gtk_widget_destroy (GTK_WIDGET (pdw));
176 session_for_each_dataset (the_session, new_pdw_cb, NULL);
178 /* Destroy the lexer only after obtaining the dataset, because the dataset
179 might depend on the lexer, if the casereader specifies inline data. (In
180 such a case then we'll always get an error message--the inline data is
181 missing, otherwise it would have been parsed in the loop above.) */
183 psppire_set_lexer (NULL);
190 /* Executes null-terminated string SYNTAX as syntax.
193 execute_syntax_string (PsppireDataWindow *window, gchar *syntax)
195 execute_const_syntax_string (window, syntax);
199 /* Executes null-terminated string SYNTAX as syntax. */
201 execute_const_syntax_string (PsppireDataWindow *window, const gchar *syntax)
203 execute_syntax (window, lex_reader_for_string (syntax, "UTF-8"));