diff options
Diffstat (limited to 'e-util/e-error.c')
-rw-r--r-- | e-util/e-error.c | 698 |
1 files changed, 0 insertions, 698 deletions
diff --git a/e-util/e-error.c b/e-util/e-error.c deleted file mode 100644 index 47d7548c70..0000000000 --- a/e-util/e-error.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include <config.h> - -#include <string.h> -#include <sys/types.h> - -#include <libxml/parser.h> -#include <libxml/xmlmemory.h> - -#include <gtk/gtk.h> -#include <glib/gi18n.h> - -#include <libedataserver/e-xml-utils.h> - -#include "e-util.h" -#include "e-util-private.h" -#include "e-error.h" - -#define d(x) - -struct _EError -{ - gchar *tag; - GPtrArray *args; -}; - -void -e_error_free (EError *error) -{ - if (error == NULL) - return; - g_free (error->tag); - /* arg strings will be freed automatically since we set a free func when - * creating the ptr array */ - g_ptr_array_free (error->args, TRUE); -} - -struct _e_error_button { - struct _e_error_button *next; - const gchar *stock; - const gchar *label; - gint response; -}; - -struct _e_error { - guint32 flags; - const gchar *id; - gint type; - gint default_response; - const gchar *title; - const gchar *primary; - const gchar *secondary; - const gchar *help_uri; - gboolean scroll; - struct _e_error_button *buttons; -}; - -struct _e_error_table { - const gchar *domain; - const gchar *translation_domain; - GHashTable *errors; -}; - -static GHashTable *error_table; - -/* ********************************************************************** */ - -static struct _e_error_button default_ok_button = { - NULL, "gtk-ok", NULL, GTK_RESPONSE_OK -}; - -static struct _e_error default_errors[] = { - { GTK_DIALOG_MODAL, "error", 3, GTK_RESPONSE_OK, N_("Evolution Error"), "{0}", "{1}", NULL, FALSE, &default_ok_button }, - { GTK_DIALOG_MODAL, "error-primary", 3, GTK_RESPONSE_OK, N_("Evolution Error"), "{0}", NULL, NULL, FALSE, &default_ok_button }, - { GTK_DIALOG_MODAL, "warning", 1, GTK_RESPONSE_OK, N_("Evolution Warning"), "{0}", "{1}", NULL, FALSE, &default_ok_button }, - { GTK_DIALOG_MODAL, "warning-primary", 1, GTK_RESPONSE_OK, N_("Evolution Warning"), "{0}", NULL, NULL, FALSE, &default_ok_button }, -}; - -/* ********************************************************************** */ - -static struct { - const gchar *name; - gint id; -} response_map[] = { - { "GTK_RESPONSE_REJECT", GTK_RESPONSE_REJECT }, - { "GTK_RESPONSE_ACCEPT", GTK_RESPONSE_ACCEPT }, - { "GTK_RESPONSE_OK", GTK_RESPONSE_OK }, - { "GTK_RESPONSE_CANCEL", GTK_RESPONSE_CANCEL }, - { "GTK_RESPONSE_CLOSE", GTK_RESPONSE_CLOSE }, - { "GTK_RESPONSE_YES", GTK_RESPONSE_YES }, - { "GTK_RESPONSE_NO", GTK_RESPONSE_NO }, - { "GTK_RESPONSE_APPLY", GTK_RESPONSE_APPLY }, - { "GTK_RESPONSE_HELP", GTK_RESPONSE_HELP }, -}; - -static gint -map_response(const gchar *name) -{ - gint i; - - for (i = 0; i < G_N_ELEMENTS (response_map); i++) - if (!strcmp(name, response_map[i].name)) - return response_map[i].id; - - return 0; -} - -static struct { - const gchar *name; - const gchar *icon; -} type_map[] = { - { "info", GTK_STOCK_DIALOG_INFO }, - { "warning", GTK_STOCK_DIALOG_WARNING }, - { "question", GTK_STOCK_DIALOG_QUESTION }, - { "error", GTK_STOCK_DIALOG_ERROR }, -}; - -static gint -map_type(const gchar *name) -{ - gint i; - - if (name) { - for (i = 0; i < G_N_ELEMENTS (type_map); i++) - if (!strcmp(name, type_map[i].name)) - return i; - } - - return 3; -} - -/* - XML format: - - <error id="error-id" type="info|warning|question|error"? response="default_response"? modal="true"? > - <title>Window Title</title>? - <primary>Primary error text.</primary>? - <secondary>Secondary error text.</secondary>? - <help uri="help uri"/> ? - <button stock="stock-button-id"? label="button label"? response="response_id"? /> * - </error> - - The tool e-error-tool is used to extract the translatable strings for - translation. - -*/ -static void -ee_load(const gchar *path) -{ - xmlDocPtr doc = NULL; - xmlNodePtr root, error, scan; - struct _e_error *e; - struct _e_error_button *lastbutton; - struct _e_error_table *table; - gchar *tmp; - - d(printf("loading error file %s\n", path)); - - doc = e_xml_parse_file (path); - if (doc == NULL) { - g_warning("Error file '%s' not found", path); - return; - } - - root = xmlDocGetRootElement(doc); - if (root == NULL - || strcmp((gchar *)root->name, "error-list") != 0 - || (tmp = (gchar *)xmlGetProp(root, (const guchar *)"domain")) == NULL) { - g_warning("Error file '%s' invalid format", path); - xmlFreeDoc(doc); - return; - } - - table = g_hash_table_lookup(error_table, tmp); - if (table == NULL) { - gchar *tmp2; - - table = g_malloc0(sizeof(*table)); - table->domain = g_strdup(tmp); - table->errors = g_hash_table_new(g_str_hash, g_str_equal); - g_hash_table_insert(error_table, (gpointer) table->domain, table); - - tmp2 = (gchar *)xmlGetProp(root, (const guchar *)"translation-domain"); - if (tmp2) { - table->translation_domain = g_strdup(tmp2); - xmlFree(tmp2); - - tmp2 = (gchar *)xmlGetProp(root, (const guchar *)"translation-localedir"); - if (tmp2) { - bindtextdomain(table->translation_domain, tmp2); - xmlFree(tmp2); - } - } - } else - g_warning("Error file '%s', domain '%s' already used, merging", path, tmp); - xmlFree(tmp); - - for (error = root->children;error;error = error->next) { - if (!strcmp((gchar *)error->name, "error")) { - tmp = (gchar *)xmlGetProp(error, (const guchar *)"id"); - if (tmp == NULL) - continue; - - e = g_malloc0(sizeof(*e)); - e->id = g_strdup(tmp); - e->scroll = FALSE; - - xmlFree(tmp); - lastbutton = (struct _e_error_button *)&e->buttons; - - tmp = (gchar *)xmlGetProp(error, (const guchar *)"modal"); - if (tmp) { - if (!strcmp(tmp, "true")) - e->flags |= GTK_DIALOG_MODAL; - xmlFree(tmp); - } - - tmp = (gchar *)xmlGetProp(error, (const guchar *)"type"); - e->type = map_type(tmp); - if (tmp) - xmlFree(tmp); - - tmp = (gchar *)xmlGetProp(error, (const guchar *)"default"); - if (tmp) { - e->default_response = map_response(tmp); - xmlFree(tmp); - } - - tmp = (gchar *)xmlGetProp(error, (const guchar *)"scroll"); - if (tmp) { - if (!strcmp(tmp, "yes")) - e->scroll = TRUE; - xmlFree(tmp); - } - - for (scan = error->children;scan;scan=scan->next) { - if (!strcmp((gchar *)scan->name, "primary")) { - if ((tmp = (gchar *)xmlNodeGetContent(scan))) { - e->primary = g_strdup(dgettext(table->translation_domain, tmp)); - xmlFree(tmp); - } - } else if (!strcmp((gchar *)scan->name, "secondary")) { - if ((tmp = (gchar *)xmlNodeGetContent(scan))) { - e->secondary = g_strdup(dgettext(table->translation_domain, tmp)); - xmlFree(tmp); - } - } else if (!strcmp((gchar *)scan->name, "title")) { - if ((tmp = (gchar *)xmlNodeGetContent(scan))) { - e->title = g_strdup(dgettext(table->translation_domain, tmp)); - xmlFree(tmp); - } - } else if (!strcmp((gchar *)scan->name, "help")) { - tmp = (gchar *)xmlGetProp(scan, (const guchar *)"uri"); - if (tmp) { - e->help_uri = g_strdup(tmp); - xmlFree(tmp); - } - } else if (!strcmp((gchar *)scan->name, "button")) { - struct _e_error_button *b; - gchar *label = NULL; - gchar *stock = NULL; - - b = g_malloc0(sizeof(*b)); - tmp = (gchar *)xmlGetProp(scan, (const guchar *)"stock"); - if (tmp) { - stock = g_strdup(tmp); - b->stock = stock; - xmlFree(tmp); - } - tmp = (gchar *)xmlGetProp(scan, (const guchar *)"label"); - if (tmp) { - label = g_strdup(dgettext(table->translation_domain, tmp)); - b->label = label; - xmlFree(tmp); - } - tmp = (gchar *)xmlGetProp(scan, (const guchar *)"response"); - if (tmp) { - b->response = map_response(tmp); - xmlFree(tmp); - } - - if (stock == NULL && label == NULL) { - g_warning("Error file '%s': missing button details in error '%s'", path, e->id); - g_free(stock); - g_free(label); - g_free(b); - } else { - lastbutton->next = b; - lastbutton = b; - } - } - } - - g_hash_table_insert(table->errors, (gpointer) e->id, e); - } - } - - xmlFreeDoc(doc); -} - -static void -ee_load_tables(void) -{ - GDir *dir; - const gchar *d; - gchar *base; - struct _e_error_table *table; - gint i; - - if (error_table != NULL) - return; - - error_table = g_hash_table_new(g_str_hash, g_str_equal); - - /* setup system error types */ - table = g_malloc0(sizeof(*table)); - table->domain = "builtin"; - table->errors = g_hash_table_new(g_str_hash, g_str_equal); - for (i = 0; i < G_N_ELEMENTS (default_errors); i++) - g_hash_table_insert(table->errors, (gpointer) default_errors[i].id, &default_errors[i]); - g_hash_table_insert(error_table, (gpointer) table->domain, table); - - /* look for installed error tables */ - base = g_build_filename (EVOLUTION_PRIVDATADIR, "errors", NULL); - dir = g_dir_open(base, 0, NULL); - if (dir == NULL) { - g_free (base); - return; - } - - while ( (d = g_dir_read_name(dir)) ) { - gchar *path; - - if (d[0] == '.') - continue; - - path = g_build_filename(base, d, NULL); - ee_load(path); - g_free(path); - } - - g_dir_close(dir); - g_free (base); -} - -/* unfortunately, gmarkup_escape doesn't expose its gstring based api :( */ -static void -ee_append_text(GString *out, const gchar *text) -{ - gchar c; - - while ( (c=*text++) ) { - if (c == '<') - g_string_append(out, "<"); - else if (c == '>') - g_string_append(out, ">"); - else if (c == '"') - g_string_append(out, """); - else if (c == '\'') - g_string_append(out, "'"); - else if (c == '&') - g_string_append(out, "&"); - else - g_string_append_c(out, c); - } -} - -static void -ee_build_label(GString *out, const gchar *fmt, GPtrArray *args, - gboolean escape_args) -{ - const gchar *end, *newstart; - gint id; - - while (fmt - && (newstart = strchr(fmt, '{')) - && (end = strchr(newstart+1, '}'))) { - g_string_append_len(out, fmt, newstart-fmt); - id = atoi(newstart+1); - if (id < args->len) { - if (escape_args) - ee_append_text(out, args->pdata[id]); - else - g_string_append(out, args->pdata[id]); - } else - g_warning("Error references argument %d not supplied by caller", id); - fmt = end+1; - } - - g_string_append(out, fmt); -} - -static void -ee_response(GtkWidget *w, guint button, struct _e_error *e) -{ - if (button == GTK_RESPONSE_HELP) { - g_signal_stop_emission_by_name(w, "response"); - e_display_help (GTK_WINDOW (w), e->help_uri); - } -} - -EError * -e_error_newv(const gchar *tag, const gchar *arg0, va_list ap) -{ - gchar *tmp; - GPtrArray *args; - EError *err = g_slice_new0 (EError); - err->tag = g_strdup (tag); - err->args = g_ptr_array_new_with_free_func (g_free); - - tmp = (gchar *)arg0; - while (tmp) { - g_ptr_array_add(args, g_strdup (tmp)); - tmp = va_arg(ap, gchar *); - } - - return err; -} - -/** - * e_error_new: - * @tag: error identifier - * @arg0: The first argument for the error formatter. The list must - * be NULL terminated. - * - * Creates a new EError. The @tag argument is used to determine - * which error to use, it is in the format domain:error-id. The NULL - * terminated list of arguments, starting with @arg0 is used to fill - * out the error definition. - **/ -EError * -e_error_new(const gchar *tag, const gchar *arg0, ...) -{ - EError *e; - va_list ap; - - va_start(ap, arg0); - e = e_error_newv(tag, arg0, ap); - va_end(ap); - - return e; -} - -GtkWidget * -e_error_new_dialog(GtkWindow *parent, EError *error) -{ - struct _e_error_table *table; - struct _e_error *e; - struct _e_error_button *b; - GtkWidget *hbox, *w, *scroll=NULL; - GtkWidget *action_area; - GtkWidget *content_area; - gchar *tmp, *domain, *id; - GString *out, *oerr; - GtkDialog *dialog; - gchar *str, *perr=NULL, *serr=NULL; - - g_return_val_if_fail (error != NULL, NULL); - - if (error_table == NULL) - ee_load_tables(); - - dialog = (GtkDialog *)gtk_dialog_new(); - action_area = gtk_dialog_get_action_area (dialog); - content_area = gtk_dialog_get_content_area (dialog); - - gtk_dialog_set_has_separator(dialog, FALSE); - - gtk_widget_ensure_style ((GtkWidget *)dialog); - gtk_container_set_border_width (GTK_CONTAINER (action_area), 12); - gtk_container_set_border_width (GTK_CONTAINER (content_area), 0); - - if (parent) - gtk_window_set_transient_for ((GtkWindow *)dialog, parent); - else - g_warning ( - "Something called %s() with a NULL parent window. " - "This is no longer legal, please fix it.", G_STRFUNC); - - domain = alloca(strlen(error->tag)+1); - strcpy(domain, error->tag); - id = strchr(domain, ':'); - if (id) - *id++ = 0; - - if ( id == NULL - || (table = g_hash_table_lookup(error_table, domain)) == NULL - || (e = g_hash_table_lookup(table->errors, id)) == NULL) { - /* setup a dummy error */ - str = g_strdup_printf(_("Internal error, unknown error '%s' requested"), error->tag); - tmp = g_strdup_printf("<span weight=\"bold\">%s</span>", str); - g_free(str); - w = gtk_label_new(NULL); - gtk_label_set_selectable((GtkLabel *)w, TRUE); - gtk_label_set_line_wrap((GtkLabel *)w, TRUE); - gtk_label_set_markup((GtkLabel *)w, tmp); - GTK_WIDGET_UNSET_FLAGS (w, GTK_CAN_FOCUS); - gtk_widget_show(w); - gtk_box_pack_start (GTK_BOX (content_area), w, TRUE, TRUE, 12); - - return (GtkWidget *)dialog; - } - - if (e->flags & GTK_DIALOG_MODAL) - gtk_window_set_modal((GtkWindow *)dialog, TRUE); - gtk_window_set_destroy_with_parent((GtkWindow *)dialog, TRUE); - - if (e->help_uri) { - w = gtk_dialog_add_button(dialog, GTK_STOCK_HELP, GTK_RESPONSE_HELP); - g_signal_connect(dialog, "response", G_CALLBACK(ee_response), e); - } - - b = e->buttons; - if (b == NULL) { - gtk_dialog_add_button(dialog, GTK_STOCK_OK, GTK_RESPONSE_OK); - } else { - for (b = e->buttons;b;b=b->next) { - if (b->stock) { - if (b->label) { -#if 0 - /* FIXME: So although this looks like it will work, it wont. - Need to do it the hard way ... it also breaks the - default_response stuff */ - w = gtk_button_new_from_stock(b->stock); - gtk_button_set_label((GtkButton *)w, b->label); - gtk_widget_show(w); - gtk_dialog_add_action_widget(dialog, w, b->response); -#endif - gtk_dialog_add_button(dialog, b->label, b->response); - } else - gtk_dialog_add_button(dialog, b->stock, b->response); - } else - gtk_dialog_add_button(dialog, b->label, b->response); - } - } - - if (e->default_response) - gtk_dialog_set_default_response(dialog, e->default_response); - - hbox = gtk_hbox_new(FALSE, 0); - gtk_container_set_border_width((GtkContainer *)hbox, 12); - - w = gtk_image_new_from_stock(type_map[e->type].icon, GTK_ICON_SIZE_DIALOG); - gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.0); - gtk_box_pack_start((GtkBox *)hbox, w, FALSE, FALSE, 12); - - out = g_string_new(""); - - if (e->title && *e->title) { - ee_build_label(out, e->title, error->args, FALSE); - gtk_window_set_title((GtkWindow *)dialog, out->str); - g_string_truncate(out, 0); - } else - gtk_window_set_title((GtkWindow *)dialog, out->str); - - if (e->primary) { - g_string_append(out, "<span weight=\"bold\" size=\"larger\">"); - ee_build_label(out, e->primary, error->args, TRUE); - g_string_append(out, "</span>\n\n"); - oerr = g_string_new(""); - ee_build_label(oerr, e->primary, error->args, FALSE); - perr = g_strdup (oerr->str); - g_string_free (oerr, TRUE); - } else - perr = g_strdup (gtk_window_get_title (GTK_WINDOW (dialog))); - - if (e->secondary) { - ee_build_label(out, e->secondary, error->args, TRUE); - oerr = g_string_new(""); - ee_build_label(oerr, e->secondary, error->args, TRUE); - serr = g_strdup (oerr->str); - g_string_free (oerr, TRUE); - } - - if (e->scroll) { - scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ((GtkScrolledWindow *)scroll, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - } - w = gtk_label_new(NULL); - gtk_label_set_selectable((GtkLabel *)w, TRUE); - gtk_label_set_line_wrap((GtkLabel *)w, TRUE); - gtk_label_set_markup((GtkLabel *)w, out->str); - GTK_WIDGET_UNSET_FLAGS (w, GTK_CAN_FOCUS); - g_string_free(out, TRUE); - if (e->scroll) { - gtk_scrolled_window_add_with_viewport ((GtkScrolledWindow *)scroll, w); - gtk_box_pack_start((GtkBox *)hbox, scroll, FALSE, FALSE, 0); - gtk_window_set_default_size ((GtkWindow *)dialog, 360, 180); - } else - gtk_box_pack_start((GtkBox *)hbox, w, TRUE, TRUE, 0); - - gtk_widget_show_all(hbox); - - gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0); - g_object_set_data_full ((GObject *) dialog, "primary", perr, g_free); - g_object_set_data_full ((GObject *) dialog, "secondary", serr, g_free); - - return (GtkWidget *)dialog; -} - -gint -e_error_run_dialog(GtkWindow *parent, EError *error) -{ - GtkWidget *w; - gint res; - - w = e_error_new_dialog(parent, error); - - res = gtk_dialog_run((GtkDialog *)w); - gtk_widget_destroy(w); - - return res; -} - -/** - * e_error_dialog_count_buttons: - * @dialog: a #GtkDialog - * - * Counts the number of buttons in @dialog's action area. - * - * Returns: number of action area buttons - **/ -guint -e_error_dialog_count_buttons (GtkDialog *dialog) -{ - GtkWidget *container; - GList *children, *iter; - guint n_buttons = 0; - - g_return_val_if_fail (GTK_DIALOG (dialog), 0); - - container = gtk_dialog_get_action_area (dialog); - children = gtk_container_get_children (GTK_CONTAINER (container)); - - /* Iterate over the children looking for buttons. */ - for (iter = children; iter != NULL; iter = iter->next) - if (GTK_IS_BUTTON (iter->data)) - n_buttons++; - - g_list_free (children); - - return n_buttons; -} - -GtkWidget * -e_error_new_dialog_for_args (GtkWindow *parent, const gchar *tag, const gchar *arg0, ...) -{ - GtkWidget *w; - EError *e; - va_list ap; - - va_start(ap, arg0); - e = e_error_newv(tag, arg0, ap); - va_end(ap); - - w = e_error_new_dialog (parent, e); - e_error_free (e); - - return w; -} - -gint -e_error_run_dialog_for_args (GtkWindow *parent, const gchar *tag, const gchar *arg0, ...) -{ - EError *e; - va_list ap; - gint response; - - va_start(ap, arg0); - e = e_error_newv(tag, arg0, ap); - va_end(ap); - - response = e_error_run_dialog (parent, e); - e_error_free (e); - - return response; -} |