1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2004, 2005, 2010 Free Software Foundation, Inc.
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/>. */
23 #define _(msgid) gettext (msgid)
24 #define N_(msgid) msgid
26 #include <libpspp/assertion.h>
27 #include <libpspp/message.h>
28 #include <libpspp/str.h>
29 #include <libpspp/msg-locator.h>
30 #include "message-dialog.h"
39 static void enqueue_msg (const struct msg *m);
40 static gboolean popup_messages (gpointer);
42 #define MAX_EARLY_MESSAGES 100
43 static GQueue *early_queue;
45 static unsigned long dropped_messages;
47 #define MAX_LATE_MESSAGES 10
48 static GQueue *late_queue;
50 static int error_cnt, warning_cnt, note_cnt;
52 static GtkBuilder *message_xml;
53 static GtkWidget *message_dialog;
56 message_dialog_init (struct source_stream *ss)
58 early_queue = g_queue_new ();
60 late_queue = g_queue_new ();
61 error_cnt = warning_cnt = note_cnt = 0;
62 msg_init (ss, enqueue_msg);
63 message_xml = builder_new ("message-dialog.ui");
64 message_dialog = get_widget_assert (message_xml, "message-dialog");
66 GTK_WIDGET_SET_FLAGS (get_widget_assert (message_xml, "close-button"),
72 message_dialog_done (void)
75 g_queue_free (early_queue);
77 g_queue_free (late_queue);
78 gtk_widget_destroy (message_dialog);
79 g_object_unref (message_xml);
83 format_message (struct msg *m, struct string *msg)
87 if (m->where.file_name)
88 ds_put_format (msg, "%s:", m->where.file_name);
89 if (m->where.line_number != -1)
90 ds_put_format (msg, "%d:", m->where.line_number);
91 if (m->where.file_name || m->where.line_number != -1)
92 ds_put_char (msg, ' ');
100 label = _("syntax error");
104 label = _("data file error");
109 label = _("PSPP error");
117 label = _("syntax warning");
121 label = _("data file warning");
126 label = _("PSPP warning");
135 label = _("syntax information");
139 label = _("data file information");
144 label = _("PSPP information");
149 ds_put_format (msg, "%s: %s\n", label, m->text);
154 enqueue_msg (const struct msg *msg)
156 struct msg *m = msg_dup (msg);
169 case MSG_N_SEVERITIES:
173 if (g_queue_get_length (early_queue) < MAX_EARLY_MESSAGES)
175 if (g_queue_is_empty (early_queue))
176 g_idle_add (popup_messages, NULL);
177 g_queue_push_tail (early_queue, m);
181 if (g_queue_get_length (late_queue) >= MAX_LATE_MESSAGES)
183 struct msg *m = g_queue_pop_head (late_queue);
187 g_queue_push_tail (late_queue, m);
192 popup_messages (gpointer unused UNUSED)
194 GtkTextBuffer *text_buffer;
196 GtkTextView *text_view;
198 struct string lead = DS_EMPTY_INITIALIZER;
199 struct string msg = DS_EMPTY_INITIALIZER;
202 gdk_threads_enter ();
204 /* Set up the dialog. */
205 if (message_xml == NULL || message_dialog == NULL)
208 /* If a pointer grab is in effect, then the combination of that, and
209 a modal dialog box, will cause an impossible situation.
210 So don't pop it up just yet.
212 if ( gdk_display_pointer_is_grabbed (gtk_widget_get_display (message_dialog)))
216 gdk_threads_leave ();
220 /* Compose the lead-in. */
221 message_cnt = error_cnt + warning_cnt + note_cnt;
222 if (dropped_messages == 0)
225 ngettext ("The PSPP processing engine reported the following message:",
226 "The PSPP processing engine reported the following messages:",
232 ngettext ("The PSPP processing engine reported %d message.",
233 "The PSPP processing engine reported %d messages.",
236 ds_put_cstr (&lead, " ");
239 ngettext ("%d of these messages are displayed below.",
240 "%d of these messages are displayed below.",
241 MAX_EARLY_MESSAGES + MAX_LATE_MESSAGES),
242 MAX_EARLY_MESSAGES + MAX_LATE_MESSAGES);
246 /* Compose the messages. */
247 while (!g_queue_is_empty (early_queue))
248 format_message (g_queue_pop_head (early_queue), &msg);
249 if (dropped_messages)
251 ds_put_format (&msg, "...\nOmitting %lu messages\n...\n",
253 dropped_messages = 0;
255 while (!g_queue_is_empty (late_queue))
256 format_message (g_queue_pop_head (late_queue), &msg);
258 text_buffer = gtk_text_buffer_new (NULL);
259 gtk_text_buffer_get_end_iter (text_buffer, &end);
260 gtk_text_buffer_insert (text_buffer, &end, ds_data (&msg), ds_length (&msg));
262 label = GTK_LABEL (get_widget_assert (message_xml, "lead-in"));
265 gtk_label_set_text (label, ds_cstr (&lead));
267 text_view = GTK_TEXT_VIEW (get_widget_assert (message_xml, "message"));
268 if (text_view == NULL)
270 gtk_text_view_set_buffer (text_view, text_buffer);
272 gtk_widget_grab_default (get_widget_assert (message_xml, "close-button"));
273 gtk_widget_grab_focus (get_widget_assert (message_xml, "close-button"));
274 gtk_dialog_run ( GTK_DIALOG (message_dialog));
275 gtk_widget_hide (message_dialog);
280 gdk_threads_leave ();
284 g_warning ("Could not create message dialog. "
285 "Is PSPPIRE properly installed?");
286 fputs (ds_cstr (&msg), stderr);
289 gdk_threads_leave ();