aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Zucci <zucchi@src.gnome.org>2004-04-16 17:57:07 +0800
committerMichael Zucci <zucchi@src.gnome.org>2004-04-16 17:57:07 +0800
commit5de7b60f7a19aad8186db52d82db3fe5e11e79d2 (patch)
treebe23bc07c50d02be9086b746024a8790dfa9bd97
parentf53eadffe11cd3bd9e05414e1484e5e648ced8b1 (diff)
downloadgsoc2013-evolution-5de7b60f7a19aad8186db52d82db3fe5e11e79d2.tar
gsoc2013-evolution-5de7b60f7a19aad8186db52d82db3fe5e11e79d2.tar.gz
gsoc2013-evolution-5de7b60f7a19aad8186db52d82db3fe5e11e79d2.tar.bz2
gsoc2013-evolution-5de7b60f7a19aad8186db52d82db3fe5e11e79d2.tar.lz
gsoc2013-evolution-5de7b60f7a19aad8186db52d82db3fe5e11e79d2.tar.xz
gsoc2013-evolution-5de7b60f7a19aad8186db52d82db3fe5e11e79d2.tar.zst
gsoc2013-evolution-5de7b60f7a19aad8186db52d82db3fe5e11e79d2.zip
Work in progress, HIG'ing and de-coupling of errors.
svn path=/trunk/; revision=25493
-rw-r--r--composer/mail-composer-errors.xml.in35
-rw-r--r--filter/filter-errors.xml.in51
-rw-r--r--mail/mail-errors.xml.in293
-rw-r--r--widgets/misc/e-error.c550
-rw-r--r--widgets/misc/e-error.h40
5 files changed, 969 insertions, 0 deletions
diff --git a/composer/mail-composer-errors.xml.in b/composer/mail-composer-errors.xml.in
new file mode 100644
index 0000000000..442891d09f
--- /dev/null
+++ b/composer/mail-composer-errors.xml.in
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<error-list domain="mail-composer">
+
+ <error id="attach" type="warning">
+ <_primary>You cannot attach the file `${0}' to this message.</_primary>
+ <_secondary>${0}</_secondary>
+ </error>
+
+ <error id="attach-notfile" type="warning">
+ <_primary>The file `${0}' is not a regular file and cannot be sent in a message.</_primary>
+ </error>
+
+ <error id="attach-directory">
+ <_primary>Directories can not be attached to Messages.</_primary>
+ <_secondary>To attach the contents of this directory, either attach the files in this directory individually, or create an archive of the directory and attach it.</_secondary>
+ </error>
+
+ <error id="recover-autosave" type="question">
+ <_title>Unfinished messages found</_title>
+ <_primary>Do you want to recover unfinished messages?</_primary>
+ <_secondary>Evolution quit unexpectedly while you were composing a new message. Recovering the message will allow you to continue where you left off.</_secondary>
+ <button _label="Don't Recover" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="Recover" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="exit-unsaved" modal="true" type="warning">
+ <_title>Warning: Modified Message</_title>
+ <_primary>Are you sure you want to discard the message, titled '{0}', you are composing?</_primary>
+ <_secondary>Closing this composer window will discard the message permanently, unless you choose to save the message in your Drafts folder. This will allow you to continue the message at a later date.</_secondary>
+ <button _label="Discard Changes" response="GTK_RESPONSE_NO"/>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="Save Message" response="GTK_RESPONSE_YES"/>
+ </error>
+
+</error-list>
diff --git a/filter/filter-errors.xml.in b/filter/filter-errors.xml.in
new file mode 100644
index 0000000000..97bbd9c8fb
--- /dev/null
+++ b/filter/filter-errors.xml.in
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<error-list domain="filter">
+
+ <error id="no-date" type="error">
+ <_primary>Missing date.</_primary>
+ <_secondary>You must choose a date.</_secondary>
+ </error>
+
+ <error id="no-file" type="error">
+ <_primary>Missing file name.</_primary>
+ <_secondary>You must specify a file name.</_secondary>
+ </error>
+
+ <error id="bad-file" type="error">
+ <_primary>File &quot;{0}&quot; does not exist or is not a regular file.</_primary>
+ <_secondary>You must specify a file name.</_secondary>
+ </error>
+
+ <error id="no-folder" type="error">
+ <_primary>Missing folder.</_primary>
+ <_secondary>You must specify a folder.</_secondary>
+ </error>
+
+ <error id="bad-regexp" type="error">
+ <_primary>Bad regular expression &quot;{0}&quot;.</_primary>
+ <_secondary>Could not compile regular expression &quot;{1}&quot;.</_secondary>
+ </error>
+
+ <error id="no-name" type="error">
+ <_primary>Missing name.</_primary>
+ <_secondary>You must name this filter.</_secondary>
+ </error>
+
+ <error id="no-name-vfolder" type="error">
+ <_primary>Missing name.</_primary>
+ <_secondary>You must name this vFolder.</_secondary>
+ </error>
+
+ <error id="bad-name-notunique" type="error">
+ <_primary>Name &quot;{0}&quot; already used.</_primary>
+ <_secondary>Please choose another name.</_secondary>
+ </error>
+
+ <error id="vfolder-no-source" type="error">
+ <_primary>No sources selected.</_primary>
+ <_secondary>You must specify at least one folder as a source.
+Either by selecting the folders individually, and/or by selecting
+all local folders, all remote folders, or both.</_secondary>
+ </error>
+
+</error-list> \ No newline at end of file
diff --git a/mail/mail-errors.xml.in b/mail/mail-errors.xml.in
new file mode 100644
index 0000000000..81a7d09af0
--- /dev/null
+++ b/mail/mail-errors.xml.in
@@ -0,0 +1,293 @@
+<?xml version="1.0"?>
+<error-list domain="mail">
+
+ <error id="camel-service-auth-invalid" type="warning">
+ <_primary>Invalid authentication</_primary>
+ <_secondary>This server does not support this type of authentication and may not support authentication at all.</_secondary>
+ </error>
+
+ <error id="camel-service-auth-failed" type="warning">
+ <_primary>Your login to your server &quot;{0}&quot; as &quot;{0}&quot; failed.</_primary>
+ <_secondary>Check to make sure your password is spelled correctly. Remember that many passwords are case sensitive; your caps lock might be on.</_secondary>
+ </error>
+
+ <error id="ask-send-html" type="question" default="GTK_RESPONSE_YES">
+ <_primary>Are you sure you want to send a message in HTML format?</_primary>
+ <_secondary>Please make sure the following recipients are willing and able to receive HTML email:
+{0}
+Send anyway?</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="_Send" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="ask-send-no-subject" type="question" default="GTK_RESPONSE_YES">
+ <_primary>Are you sure you want to send a message without a subject?</_primary>
+ <_secondary>Adding a meaningful Subject line to your messages will give your recipients an idea of what your mail is about.</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="_Send" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="ask-send-only-bcc-contact" type="question" default="GTK_RESPONSE_YES">
+ <_primary>Are you sure you want to send a message with only BCC recipients?</_primary>
+ <_secondary>The contact list you are sending to is configured to hide list recipients.
+
+Many email systems add an Apparently-To header to messages that only have BCC recipients. This header, if added, will list all of your recipients in your message. To avoid this, you should add at least one To: or CC: recipient. </_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="_Send" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="ask-send-only-bcc" type="warning" default="GTK_RESPONSE_YES">
+ <_primary>Are you sure you want to send a message with only BCC recipients?</_primary>
+ <_secondary>Many email systems add an Apparently-To header to messages that only have BCC recipients. This header, if added, will list all of your recipients to your message anyway. To avoid this, you should add at least one To: or CC: recipient.</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="_Send" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="send-no-recipients" type="warning">
+ <_primary>This message cannot be sent because you have not specified any Recipients</_primary>
+ <_secondary>Please enter a valid email address in the To: field. You can search for email addresses by clicking on the To: button next to the entry box.</_secondary>
+ </error>
+
+ <error id="ask-default-drafts" type="question" default="GTK_RESPONSE_YES">
+ <_primary>Use default drafts folder?</_primary>
+ <_secondary>Unable to open the drafts folder for this account. Use the system drafts folder instead?</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="Use _Default" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="ask-expunge" type="question" default="GTK_RESPONSE_CANCEL">
+ <_primary>Are you sure you want to permanently remove all the deleted message in folder &quot;{0}&quot;?</_primary>
+ <_secondary>If you continue, you will not be able to recover these messages.</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="_Expunge" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="ask-empty-trash" type="warning" default="GTK_RESPONSE_CANCEL">
+ <_primary>Are you sure you want to permanently remove all the deleted messages in all folders?</_primary>
+ <_secondary>If you continue, you will not be able to recover these messages.</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="_Empty Trash" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="exit-unsaved" type="warning" default="GTK_RESPONSE_NO">
+ <_primary>You have unsent messages, do you wish to quit anyway?</_primary>
+ <_secondary>If you quit, these messages will not be sent until Evolution is started again.</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_NO"/>
+ <button stock="gtk-quit" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="camel-exception" type="warning">
+ <_primary>Your message message, with the subject &quot;{0}&quot; was not delivered.</_primary>
+ <_secondary>The message was sent via the &quot;sendmail&quot; external application. Sendmail reports the following error: status 67: mail not sent.
+The message is stored in the Outbox folder. Check the message for errors and resend.</_secondary>
+ </error>
+
+ <error id="async-error" type="error">
+ <_primary>Error while {0}.</_primary>
+ <_secondary>{1}.</_secondary>
+ </error>
+
+ <error id="async-error-nodescribe" type="error">
+ <_primary>Error while performing operation.</_primary>
+ <_secondary>{0}.</_secondary>
+ </error>
+
+ <error id="session-message-info" type="info">
+ <_primary>{0}</_primary>
+ </error>
+
+ <error id="session-message-info-cancel" type="info" default="GTK_RESPONSE_CANCEL">
+ <_primary>{0}</_primary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button stock="gtk-ok" response="GTK_RESPONSE_OK"/>
+ </error>
+
+ <error id="session-message-warning" type="warning">
+ <_primary>{0}</_primary>
+ </error>
+
+ <error id="session-message-warning-cancel" type="warning" default="GTK_RESPONSE_CANCEL">
+ <_primary>{0}</_primary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button stock="gtk-ok" response="GTK_RESPONSE_OK"/>
+ </error>
+
+ <error id="session-message-error" type="info">
+ <_primary>{0}</_primary>
+ </error>
+
+ <error id="session-message-error-cancel" type="info" default="GTK_RESPONSE_CANCEL">
+ <_primary>{0}</_primary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button stock="gtk-ok" response="GTK_RESPONSE_OK"/>
+ </error>
+
+ <error id="ask-session-password" type="question" default="GTK_RESPONSE_OK">
+ <_primary>Enter password for {0}</_primary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button stock="gtk-ok" response="GTK_RESPONSE_OK"/>
+ </error>
+
+ <error id="filter-load-error" type="error">
+ <_primary>Error loading filter definitions.</_primary>
+ <_secondary>{0}</_secondary>
+ </error>
+
+ <error id="no-save-path" type="error">
+ <_primary>Cannot save to directory &quot;{0}&quot;.</_primary>
+ <_secondary>{1}</_secondary>
+ </error>
+
+ <error id="ask-save-path-overwrite" type="error" default="GTK_RESPONSE_CANCEL">
+ <_title>Overwrite file?</_title>
+ <_primary>File exists &quot;{0}&quot;.</_primary>
+ <_secondary>Do you wish to overwrite it?</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button _label="_Overwrite" response="GTK_RESPONSE_OK"/>
+ </error>
+
+ <error id="no-create-path" type="error">
+ <_primary>Cannot save to file &quot;{0}&quot;.</_primary>
+ <_secondary>Cannot create the save directory, because &quot;{1}&quot;</_secondary>
+ </error>
+
+ <error id="no-create-tmp-path" type="error">
+ <_primary>Cannot create temporary save directory.</_primary>
+ <_secondary>Because &quot;{1}&quot;.</_secondary>
+ </error>
+
+ <error id="no-write-path-exists" type="error">
+ <_primary>Cannot save to file &quot;{0}&quot;.</_primary>
+ <_secondary>File exists but cannot overwrite it.</_secondary>
+ </error>
+
+ <error id="no-write-path-notfile" type="error">
+ <_primary>Cannot save to file &quot;{0}&quot;.</_primary>
+ <_secondary>File exists but is not a regular file.</_secondary>
+ </error>
+
+ <error id="no-delete-folder" type="error">
+ <_primary>Cannot delete folder &quot;{0}&quot;.</_primary>
+ <_secondary>Because &quot;{1}&quot;.</_secondary>
+ </error>
+
+ <error id="no-delete-spethal-folder" type="error">
+ <_primary>Cannot delete system folder &quot;{0}&quot;.</_primary>
+ <_secondary>System folders are required for Ximian Evolution to function correctly and cannot be renamed, moved, or deleted.</_secondary>
+ </error>
+
+ <error id="no-rename-spethal-folder" type="error">
+ <_primary>Cannot rename or move system folder &quot;{0}&quot;.</_primary>
+ <_secondary>System folders are required for Ximian Evolution to function correctly and cannot be renamed, moved, or deleted.</_secondary>
+ </error>
+
+ <error id="ask-delete-folder" type="question" default="GTK_RESPONSE_CANCEL">
+ <_title>Delete &quot;{0}&quot;?</_title>
+ <_primary>Really delete folder &quot;{0}&quot; and all of its subfolders?</_primary>
+ <_secondary>If you delete the folder, all of its contents and its subfolders contents will be deleted permanently.</_secondary>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button stock="gtk-delete" response="GTK_RESPONSE_OK"/>
+ </error>
+
+ <error id="no-rename-folder-exists" type="error">
+ <_primary>Cannot rename &quot;{0}&quot; to &quot;{1}&quot;.</_primary>
+ <_secondary>A folder named &quot;{1}&quot; already exists. Please use a different name.</_secondary>
+ </error>
+
+ <error id="no-rename-folder" type="error">
+ <_primary>Cannot rename &quot;{0}&quot; to &quot;{1}&quot;.</_primary>
+ <_secondary>Because &quot;{2}&quot;.</_secondary>
+ </error>
+
+ <error id="no-move-folder-nostore" type="error">
+ <_primary>Cannot move folder &quot;{0}&quot; to &quot;{1}&quot;.</_primary>
+ <_secondary>Cannot open source &quot;{2}&quot;.</_secondary>
+ </error>
+
+ <error id="no-move-folder-to-nostore" type="error">
+ <_primary>Cannot move folder &quot;{0}&quot; to &quot;{1}&quot;.</_primary>
+ <_secondary>Cannot open target &quot;{2}&quot;.</_secondary>
+ </error>
+
+ <error id="no-copy-folder-nostore" type="error">
+ <_primary>Cannot copy folder &quot;{0}&quot; to &quot;{1}&quot;.</_primary>
+ <_secondary>Cannot open source &quot;{2}&quot;.</_secondary>
+ </error>
+
+ <error id="no-copy-folder-to-nostore" type="error">
+ <_primary>Cannot copy folder &quot;{0}&quot; to &quot;{1}&quot;.</_primary>
+ <_secondary>Cannot open target &quot;{2}&quot;.</_secondary>
+ </error>
+
+ <error id="no-create-folder-nostore" type="error">
+ <_primary>Cannot create folder &quot;{0}&quot;.</_primary>
+ <_secondary>Cannot open source &quot;{1}&quot;</_secondary>
+ </error>
+
+ <error id="account-incomplete" type="error">
+ <_primary>Cannot save changes to account.</_primary>
+ <_secondary>You have not filled in all of the required information.</_secondary>
+ </error>
+
+ <error id="account-notunique" type="error">
+ <_primary>Cannot save changes to account.</_primary>
+ <_secondary>You may not create two accounts with the same name.</_secondary>
+ </error>
+
+ <error id="ask-delete-account" type="question" default="GTK_RESPONSE_NO" modal="true">
+ <_title>Delete account?</_title>
+ <_primary>Are you sure you want to delete this account?</_primary>
+ <_secondary>If you proceed, the account information will be deleted permanently.</_secondary>
+ <button stock="gtk-delete" response="GTK_RESPONSE_YES"/>
+ <button stock="gtk-no" _label="Don't delete" response="GTK_RESPONSE_NO"/>
+ </error>
+
+ <error id="no-save-signature" type="error">
+ <_primary>Could not save signature file.</_primary>
+ <_secondary>Because &quot;{0}&quot;.</_secondary>
+ </error>
+
+ <error id="signature-notscript" type="error">
+ <_primary>Cannot set signature script &quot;{0}&quot;.</_primary>
+ <_secondary>The script file must exist and be executable.</_secondary>
+ </error>
+
+ <error id="ask-signature-changed" type="question" default="GTK_RESPONSE_YES">
+ <_title>Discard changed?</_title>
+ <_primary>Do you wish to save your changes?</_primary>
+ <_secondary>This signature has been changed, but has not been saved.</_secondary>
+ <button _label="_Discard changes" response="GTK_RESPONSE_NO"/>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button stock="gtk-save" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="vfolder-notexist" type="error">
+ <_primary>Cannot edit vFolder &quot;{0}&quot; as it does not exist.</_primary>
+ <_secondary>This folder may have been added implictly, go to the virtual folder editor to add it explictly, if required.</_secondary>
+ </error>
+
+ <error id="vfolder-notunique" type="error">
+ <_primary>Cannot add vFolder &quot;{0}&quot;.</_primary>
+ <_secondary>A folder named &quot;{1}&quot; already exists. Please use a different name.</_secondary>
+ </error>
+
+ <error id="vfolder-updated" type="info">
+ <_primary>vFolders automatically updated.</_primary>
+ <_secondary>The following vFolder(s):
+{0}
+Used the now removed folder:
+ &quot;{1}&quot;
+And have been updated.</_secondary>
+ </error>
+
+ <error id="filter-updated" type="info">
+ <_primary>Mail filters automatically updated.</_primary>
+ <_secondary>The following filter rule(s):
+{0}
+Used the now removed folder:
+ &quot;{1}&quot;
+And have been updated.</_secondary>
+ </error>
+
+</error-list>
+
diff --git a/widgets/misc/e-error.c b/widgets/misc/e-error.c
new file mode 100644
index 0000000000..f7cc9ee7bf
--- /dev/null
+++ b/widgets/misc/e-error.c
@@ -0,0 +1,550 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
+ * Authors: Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2004 Novell Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+
+#include <glib.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkimage.h>
+
+#include <libgnome/gnome-i18n.h>
+
+#include "e-error.h"
+
+#define d(x) x
+
+struct _e_error_button {
+ struct _e_error_button *next;
+ char *stock;
+ char *label;
+ int response;
+};
+
+struct _e_error {
+ guint32 flags;
+ char *id;
+ int type;
+ int default_response;
+ char *title;
+ char *primary;
+ char *secondary;
+ struct _e_error_button *buttons;
+};
+
+struct _e_error_table {
+ char *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}", &default_ok_button },
+ { GTK_DIALOG_MODAL, "error-primary", 3, GTK_RESPONSE_OK, N_("Evolution Error"), "{0}", NULL, &default_ok_button },
+ { GTK_DIALOG_MODAL, "warning", 1, GTK_RESPONSE_OK, N_("Evolution Warning"), "{0}", "{1}", &default_ok_button },
+ { GTK_DIALOG_MODAL, "warning-primary", 1, GTK_RESPONSE_OK, N_("Evolution Warning"), "{0}", NULL, &default_ok_button },
+};
+
+/* ********************************************************************** */
+
+static struct {
+ char *name;
+ int 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 int
+map_response(const char *name)
+{
+ int i;
+
+ for (i=0;i<sizeof(response_map)/sizeof(response_map[0]);i++)
+ if (!strcmp(name, response_map[i].name))
+ return response_map[i].id;
+
+ return 0;
+}
+
+static struct {
+ const char *name;
+ const char *icon;
+ const char *title;
+} type_map[] = {
+ { "info", GTK_STOCK_DIALOG_INFO, N_("Evolution Information") },
+ { "warning", GTK_STOCK_DIALOG_WARNING, N_("Evolution Warning") },
+ { "question", GTK_STOCK_DIALOG_QUESTION, N_("Evolution Query") },
+ { "error", GTK_STOCK_DIALOG_ERROR, N_("Evolution Error") },
+};
+
+static int
+map_type(const char *name)
+{
+ int i;
+
+ if (name) {
+ for (i=0;i<sizeof(type_map)/sizeof(type_map[0]);i++)
+ if (!strcmp(name, type_map[i].name))
+ return i;
+ }
+
+ return 3;
+}
+
+static const GList *lang_list;
+
+/* Finds the right node for the current language. */
+static xmlNodePtr
+find_node(xmlNodePtr base, const char *name)
+{
+ const GList *l;
+ xmlNodePtr scan, langc=NULL;
+
+ if (lang_list == NULL)
+ lang_list = gnome_i18n_get_language_list("LC_MESSAGES");
+
+ /* This is, like, way shitful, very slow, terribly inefficient ... sigh */
+ for (l=lang_list;l;l=l->next) {
+ const char *lang = l->data;
+
+ for (scan = base;scan;scan=scan->next) {
+ if (!strcmp(scan->name, name)) {
+ char *xmllang = xmlGetProp(scan, "xml:lang");
+
+ if (xmllang) {
+ if (!strcmp(xmllang, lang)) {
+ xmlFree(xmllang);
+ return scan;
+ }
+ xmlFree(xmllang);
+ } else {
+ langc = scan;
+ if (strcmp(lang, "C") == 0)
+ return scan;
+ }
+ }
+ }
+ }
+
+ return langc;
+}
+
+/*
+ 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>?
+ <button ( stock="stock-button-id" | _label="button label" ) response="response_id"? > *
+ </error>
+
+ Because we use intltool we need to do some weird shit to do with
+ languages. title, primary and secondary will be expanded into
+ per-language tags, specified using xml:lang property.
+
+ The _label property will remain as plain english and we need to use
+ gettext to extract it.
+*/
+static void
+ee_load(const char *path)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root, error, scan, node;
+ struct _e_error *e;
+ struct _e_error_button *lastbutton;
+ struct _e_error_table *table;
+ char *tmp;
+
+ d(printf("loading error file %s\n", path));
+
+ doc = xmlParseFile(path);
+ if (doc == NULL) {
+ g_warning("Error file '%s' not found", path);
+ return;
+ }
+
+ root = xmlDocGetRootElement(doc);
+ if (root == NULL
+ || strcmp(root->name, "error-list") != 0
+ || (tmp = xmlGetProp(root, "domain")) == NULL) {
+ g_warning("Error file '%s' invalid format", path);
+ xmlFreeDoc(doc);
+ return;
+ }
+
+ table = g_malloc0(sizeof(*table));
+ table->domain = g_strdup(tmp);
+ g_free(tmp);
+ table->errors = g_hash_table_new(g_str_hash, g_str_equal);
+
+ for (error = root->children;error;error = error->next) {
+ if (!strcmp(error->name, "error")) {
+ tmp = xmlGetProp(error, "id");
+ if (tmp == NULL)
+ continue;
+
+ e = g_malloc0(sizeof(*e));
+ e->id = g_strdup(tmp);
+ xmlFree(tmp);
+ lastbutton = (struct _e_error_button *)&e->buttons;
+
+ tmp = xmlGetProp(error, "modal");
+ if (tmp) {
+ if (!strcmp(tmp, "true"))
+ e->flags |= GTK_DIALOG_MODAL;
+ xmlFree(tmp);
+ }
+
+ tmp = xmlGetProp(error, "type");
+ e->type = map_type(tmp);
+ if (tmp)
+ xmlFree(tmp);
+
+ tmp = xmlGetProp(error, "default");
+ if (tmp) {
+ e->default_response = map_response(tmp);
+ xmlFree(tmp);
+ }
+
+ node = find_node(error->children, "primary");
+ if (node && (tmp = xmlNodeGetContent(node))) {
+ e->primary = g_strdup(tmp);
+ xmlFree(tmp);
+ }
+
+ node = find_node(error->children, "secondary");
+ if (node && (tmp = xmlNodeGetContent(node))) {
+ e->secondary = g_strdup(tmp);
+ xmlFree(tmp);
+ }
+
+ node = find_node(error->children, "title");
+ if (node && (tmp = xmlNodeGetContent(node))) {
+ e->title = g_strdup(tmp);
+ xmlFree(tmp);
+ }
+
+ for (scan = error->children;scan;scan=scan->next) {
+ if (!strcmp(scan->name, "button")) {
+ struct _e_error_button *b;
+
+ b = g_malloc0(sizeof(*b));
+ tmp = xmlGetProp(scan, "stock");
+ if (tmp) {
+ b->stock = g_strdup(tmp);
+ xmlFree(tmp);
+ }
+ tmp = xmlGetProp(scan, "label");
+ if (tmp) {
+ b->label = g_strdup(_(tmp));
+ xmlFree(tmp);
+ }
+ tmp = xmlGetProp(scan, "response");
+ if (tmp) {
+ b->response = map_response(tmp);
+ xmlFree(tmp);
+ }
+
+ if (b->stock == NULL && b->label == NULL) {
+ g_warning("Error file '%s': missing button details in error '%s'", path, e->id);
+ g_free(b->stock);
+ g_free(b->label);
+ g_free(b);
+ } else {
+ lastbutton->next = b;
+ lastbutton = b;
+ }
+ }
+ }
+
+ g_hash_table_insert(table->errors, e->id, e);
+ }
+ }
+
+ xmlFreeDoc(doc);
+
+ g_hash_table_insert(error_table, table->domain, table);
+}
+
+static void
+ee_load_tables(void)
+{
+ DIR *dir;
+ struct dirent *d;
+ const char *base = EVOLUTION_PRIVDATADIR "/errors";
+ struct _e_error_table *table;
+ int 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 = "system";
+ table->errors = g_hash_table_new(g_str_hash, g_str_equal);
+ for (i=0;i<sizeof(default_errors)/sizeof(default_errors[0]);i++)
+ g_hash_table_insert(table->errors, default_errors[i].id, &default_errors[i]);
+ g_hash_table_insert(error_table, table->domain, table);
+
+ /* look for installed error tables */
+ dir = opendir(base);
+ if (dir == NULL)
+ return;
+
+ while ( (d = readdir(dir)) ) {
+ char *path;
+
+ if (d->d_name[0] == '.')
+ continue;
+
+ path = g_build_filename(base, d->d_name, NULL);
+ ee_load(path);
+ g_free(path);
+ }
+
+ closedir(dir);
+}
+
+static void
+ee_build_label(GString *out, const char *fmt, GPtrArray *args)
+{
+ const char *end, *newstart;
+ int 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)
+ 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);
+}
+
+GtkWidget *
+e_error_newv(GtkWindow *parent, const char *tag, const char *arg0, va_list ap)
+{
+ struct _e_error_table *table;
+ struct _e_error *e;
+ struct _e_error_button *b;
+ GtkWidget *hbox, *w;
+ char *tmp, *domain, *id;
+ GString *out;
+ GPtrArray *args;
+ GtkDialog *dialog;
+
+ if (error_table == NULL)
+ ee_load_tables();
+
+ dialog = (GtkDialog *)gtk_dialog_new();
+ gtk_dialog_set_has_separator(dialog, FALSE);
+
+ if (parent)
+ gtk_window_set_transient_for((GtkWindow *)dialog, parent);
+
+ domain = alloca(strlen(tag)+1);
+ strcpy(domain, 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 */
+ tmp = g_strdup_printf(_("<span weight=\"bold\">Internal error, unknown error '%s' requested</span>"), tag);
+ w = gtk_label_new(NULL);
+ gtk_label_set_line_wrap((GtkLabel *)w, TRUE);
+ gtk_label_set_markup((GtkLabel *)w, tmp);
+ gtk_widget_show(w);
+ gtk_box_pack_start((GtkBox *)dialog->vbox, 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);
+
+ 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) {
+ /* TODO: allow stock icons on non-stock labels */
+ if (b->stock)
+ 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_box_pack_start((GtkBox *)hbox, w, TRUE, TRUE, 12);
+
+ args = g_ptr_array_new();
+ tmp = (char *)arg0;
+ while (tmp) {
+ g_ptr_array_add(args, tmp);
+ tmp = va_arg(ap, char *);
+ }
+
+ out = g_string_new("");
+
+ if (e->title) {
+ ee_build_label(out, _(e->title), args);
+ gtk_window_set_title((GtkWindow *)dialog, _(e->title));
+ g_string_truncate(out, 0);
+ } else
+ gtk_window_set_title((GtkWindow *)dialog, _(type_map[e->type].title));
+
+
+ if (e->primary) {
+ g_string_append(out, "<span weight=\"bold\" size=\"larger\">");
+ ee_build_label(out, _(e->primary), args);
+ g_string_append(out, "</span>\n\n");
+ }
+
+ if (e->secondary)
+ ee_build_label(out, _(e->secondary), args);
+
+ g_ptr_array_free(args, TRUE);
+
+ w = gtk_label_new(NULL);
+ gtk_label_set_line_wrap((GtkLabel *)w, TRUE);
+ gtk_label_set_markup((GtkLabel *)w, out->str);
+ g_string_free(out, TRUE);
+ gtk_box_pack_start((GtkBox *)hbox, w, FALSE, FALSE, 0);
+ gtk_widget_show_all(hbox);
+
+ gtk_box_pack_start((GtkBox *)dialog->vbox, hbox, TRUE, TRUE, 0);
+
+ return (GtkWidget *)dialog;
+}
+
+/**
+ * e_error_new:
+ * @parent:
+ * @tag: error identifier
+ * @arg0: The first argument for the error formatter. The list must
+ * be NULL terminated.
+ *
+ * Creates a new error widget. 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.
+ *
+ * Return value: A GtkDialog which can be used for showing an error
+ * dialog asynchronously.
+ **/
+struct _GtkWidget *
+e_error_new(struct _GtkWindow *parent, const char *tag, const char *arg0, ...)
+{
+ GtkWidget *w;
+ va_list ap;
+
+ va_start(ap, arg0);
+ w = e_error_newv(parent, tag, arg0, ap);
+ va_end(ap);
+
+ return w;
+}
+
+int
+e_error_runv(GtkWindow *parent, const char *tag, const char *arg0, va_list ap)
+{
+ GtkWidget *w;
+ int res;
+
+ w = e_error_newv(parent, tag, arg0, ap);
+
+ res = gtk_dialog_run((GtkDialog *)w);
+ gtk_widget_destroy(w);
+
+ return res;
+}
+
+/**
+ * e_error_run:
+ * @parent:
+ * @tag:
+ * @arg0:
+ *
+ * Sets up, displays, runs and destroys a standard evolution error
+ * dialog based on @tag, which is in the format domain:error-id.
+ *
+ * Return value: The response id of the button pressed.
+ **/
+int
+e_error_run(GtkWindow *parent, const char *tag, const char *arg0, ...)
+{
+ GtkWidget *w;
+ va_list ap;
+ int res;
+
+ va_start(ap, arg0);
+ w = e_error_newv(parent, tag, arg0, ap);
+ va_end(ap);
+
+ res = gtk_dialog_run((GtkDialog *)w);
+ gtk_widget_destroy(w);
+
+ return res;
+}
+
+
diff --git a/widgets/misc/e-error.h b/widgets/misc/e-error.h
new file mode 100644
index 0000000000..9da24e6004
--- /dev/null
+++ b/widgets/misc/e-error.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
+ * Authors: Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2004 Novell Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _E_ERROR_H
+#define _E_ERROR_H
+
+#include <stdarg.h>
+
+struct _GtkWindow;
+
+#define E_ERROR_WARNING "system:warning"
+#define E_ERROR_WARNING_PRIMARY "system:warning-primary"
+#define E_ERROR_ERROR "system:error"
+#define E_ERROR_ERROR_PRIMARY "system:error-primary"
+
+struct _GtkWidget *e_error_new(struct _GtkWindow *parent, const char *tag, const char *arg0, ...);
+struct _GtkWidget *e_error_newv(struct _GtkWindow *parent, const char *tag, const char *arg0, va_list ap);
+
+int e_error_run(struct _GtkWindow *parent, const char *tag, const char *arg0, ...);
+int e_error_runv(struct _GtkWindow *parent, const char *tag, const char *arg0, va_list ap);
+
+#endif /* !_E_ERROR_H */