X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fmessage-dialog.c;h=7513295323988677b38c26807cff73b96d10b04a;hb=b5c82cc9aabe7e641011130240ae1b2e84348e23;hp=6e93f7e6b3a7d77d8d10a5918de1c58be87778ec;hpb=a19b858e0ac3c69e4a28c0ca6d8674427268a863;p=pspp-builds.git diff --git a/src/ui/gui/message-dialog.c b/src/ui/gui/message-dialog.c index 6e93f7e6..75132953 100644 --- a/src/ui/gui/message-dialog.c +++ b/src/ui/gui/message-dialog.c @@ -1,11 +1,9 @@ -/* - PSPPIRE --- A Graphical User Interface for PSPP - Copyright (C) 2004,2005 Free Software Foundation - Written by John Darrington +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,154 +12,278 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ + along with this program. If not, see . */ #include #include #include +#include +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + #include +#include +#include #include "message-dialog.h" +#include "progname.h" #include -#include +#include #include "helper.h" -extern GladeXML *xml; - -#define _(A) A +static void enqueue_msg (const struct msg *m); +static gboolean popup_messages (gpointer); +#define MAX_EARLY_MESSAGES 100 +static GQueue *early_queue; -void -vmsg(int klass, const char *fmt, va_list args) -{ - gchar *msg = 0; - gchar *text = g_strdup_vprintf (fmt, args); +static unsigned long dropped_messages; - gint message_type; +#define MAX_LATE_MESSAGES 10 +static GQueue *late_queue; - switch (klass) - { - case SE: - case IE: - case DE: - case ME: - message_type = GTK_MESSAGE_ERROR; - break; - case SW: - case DW: - case MW: - message_type = GTK_MESSAGE_WARNING; - break; - case SM: - case IS: - case MM: - default: - message_type = GTK_MESSAGE_INFO; - break; - }; - - switch (klass) - { - case SE: - case SW: - case SM: - msg = g_strdup(_("Script Error")); - break; +static int error_cnt, warning_cnt, note_cnt; - case IE: - case IS: - msg = g_strdup(_("Installation Error")); - break; +static GtkBuilder *message_xml; +static GtkWidget *message_dialog; - case DE: - case DW: - msg = g_strdup(_("Data File Error")); - break; - - case ME: - case MW: - case MM: - default: - msg = g_strdup(_("PSPP Error")); - break; - }; - - GtkWindow *parent = GTK_WINDOW(get_widget_assert(xml, "data_editor")); - - GtkWidget *dialog = gtk_message_dialog_new(parent, - GTK_DIALOG_MODAL, - message_type, - GTK_BUTTONS_CLOSE, - msg); - - - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), text); - - g_free(text); - g_free(msg); - - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - - gtk_dialog_run(GTK_DIALOG(dialog)); +void +message_dialog_init (struct source_stream *ss) +{ + early_queue = g_queue_new (); + dropped_messages = 0; + late_queue = g_queue_new (); + error_cnt = warning_cnt = note_cnt = 0; + msg_init (ss, enqueue_msg); + message_xml = builder_new ("message-dialog.ui"); + message_dialog = get_widget_assert (message_xml, "message-dialog"); - gtk_widget_destroy (dialog); + GTK_WIDGET_SET_FLAGS (get_widget_assert (message_xml, "close-button"), + GTK_CAN_DEFAULT); } - -void -msg(int klass, const char *fmt, ...) +void +message_dialog_done (void) { - va_list ap; - va_start(ap, fmt); - vmsg(klass, fmt, ap); - va_end(ap); + msg_done (); + g_queue_free (early_queue); + dropped_messages = 0; + g_queue_free (late_queue); + gtk_widget_destroy (message_dialog); + g_object_unref (message_xml); } - -void -err_vmsg (const struct error *e, const char *format, va_list args) +static void +format_message (struct msg *m, struct string *msg) { - vmsg(e->class, format, args); -} + const char *label; + if (m->where.file_name) + ds_put_format (msg, "%s:", m->where.file_name); + if (m->where.line_number != -1) + ds_put_format (msg, "%d:", m->where.line_number); + if (m->where.file_name || m->where.line_number != -1) + ds_put_char (msg, ' '); -void -err_assert_fail(const char *expr, const char *file, int line) -{ - msg(ME, "Assertion failed: %s:%d; (%s)\n",file,line,expr); + switch (m->severity) + { + case MSG_ERROR: + switch (m->category) + { + case MSG_SYNTAX: + label = _("syntax error"); + break; + + case MSG_DATA: + label = _("data file error"); + break; + + case MSG_GENERAL: + default: + label = _("PSPP error"); + break; + } + break; + case MSG_WARNING: + switch (m->category) + { + case MSG_SYNTAX: + label = _("syntax warning"); + break; + + case MSG_DATA: + label = _("data file warning"); + break; + + case MSG_GENERAL: + default: + label = _("PSPP warning"); + break; + } + break; + case MSG_NOTE: + default: + switch (m->category) + { + case MSG_SYNTAX: + label = _("syntax information"); + break; + + case MSG_DATA: + label = _("data file information"); + break; + + case MSG_GENERAL: + default: + label = _("PSPP information"); + break; + } + break; + } + ds_put_format (msg, "%s: %s\n", label, m->text); + msg_destroy (m); } -/* The GUI is always interactive. - So this function does nothing */ -void -err_cond_fail(void) +static void +enqueue_msg (const struct msg *msg) { -} + struct msg *m = msg_dup (msg); + switch (m->severity) + { + case MSG_ERROR: + error_cnt++; + break; + case MSG_WARNING: + warning_cnt++; + break; + case MSG_NOTE: + note_cnt++; + break; + } -void -err_failure(void) -{ - msg(ME, _("Terminating NOW due to fatal error")); - gtk_main_quit(); + if (g_queue_get_length (early_queue) < MAX_EARLY_MESSAGES) + { + if (g_queue_is_empty (early_queue)) + g_idle_add (popup_messages, NULL); + g_queue_push_tail (early_queue, m); + } + else + { + if (g_queue_get_length (late_queue) >= MAX_LATE_MESSAGES) + { + struct msg *m = g_queue_pop_head (late_queue); + msg_destroy (m); + dropped_messages++; + } + g_queue_push_tail (late_queue, m); + } } - -/* FIXME: This is a stub . - * A temporary workaround until getl.c is rearranged - */ -void -err_location (struct file_locator *f) +static gboolean +popup_messages (gpointer unused UNUSED) { - f->filename = 0; - f->line_number = -1; + GtkTextBuffer *text_buffer; + GtkTextIter end; + GtkTextView *text_view; + GtkLabel *label; + struct string lead = DS_EMPTY_INITIALIZER; + struct string msg = DS_EMPTY_INITIALIZER; + int message_cnt; + + gdk_threads_enter (); + + /* Set up the dialog. */ + if (message_xml == NULL || message_dialog == NULL) + goto use_fallback; + + /* If a pointer grab is in effect, then the combination of that, and + a modal dialog box, will cause an impossible situation. + So don't pop it up just yet. + */ + if ( gdk_display_pointer_is_grabbed (gtk_widget_get_display (message_dialog))) + { + ds_destroy (&lead); + ds_destroy (&msg); + gdk_threads_leave (); + return TRUE; + } + + /* Compose the lead-in. */ + message_cnt = error_cnt + warning_cnt + note_cnt; + if (dropped_messages == 0) + ds_put_format ( + &lead, + ngettext ("The PSPP processing engine reported the following message:", + "The PSPP processing engine reported the following messages:", + message_cnt)); + else + { + ds_put_format ( + &lead, + ngettext ("The PSPP processing engine reported %d message.", + "The PSPP processing engine reported %d messages.", + message_cnt), + message_cnt); + ds_put_cstr (&lead, " "); + ds_put_format ( + &lead, + ngettext ("%d of these messages are displayed below.", + "%d of these messages are displayed below.", + MAX_EARLY_MESSAGES + MAX_LATE_MESSAGES), + MAX_EARLY_MESSAGES + MAX_LATE_MESSAGES); + } + + + /* Compose the messages. */ + while (!g_queue_is_empty (early_queue)) + format_message (g_queue_pop_head (early_queue), &msg); + if (dropped_messages) + { + ds_put_format (&msg, "...\nOmitting %lu messages\n...\n", + dropped_messages); + dropped_messages = 0; + } + while (!g_queue_is_empty (late_queue)) + format_message (g_queue_pop_head (late_queue), &msg); + + text_buffer = gtk_text_buffer_new (NULL); + gtk_text_buffer_get_end_iter (text_buffer, &end); + gtk_text_buffer_insert (text_buffer, &end, ds_data (&msg), ds_length (&msg)); + + label = GTK_LABEL (get_widget_assert (message_xml, "lead-in")); + if (label == NULL) + goto use_fallback; + gtk_label_set_text (label, ds_cstr (&lead)); + + text_view = GTK_TEXT_VIEW (get_widget_assert (message_xml, "message")); + if (text_view == NULL) + goto use_fallback; + gtk_text_view_set_buffer (text_view, text_buffer); + + gtk_widget_grab_default (get_widget_assert (message_xml, "close-button")); + gtk_widget_grab_focus (get_widget_assert (message_xml, "close-button")); + gtk_dialog_run ( GTK_DIALOG (message_dialog)); + gtk_widget_hide (message_dialog); + + ds_destroy (&lead); + ds_destroy (&msg); + + gdk_threads_leave (); + return FALSE; + +use_fallback: + g_warning ("Could not create message dialog. " + "Is PSPPIRE properly installed?"); + fputs (ds_cstr (&msg), stderr); + ds_destroy (&lead); + ds_destroy (&msg); + gdk_threads_leave (); + return FALSE; }