diff options
25 files changed, 1880 insertions, 3284 deletions
diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 63fce88fbe..0c7f7b3250 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -38,10 +38,10 @@ eutilinclude_HEADERS = \ e-print.h \ e-plugin.h \ e-plugin-ui.h \ - e-plugin-util.h \ e-selection.h \ e-sorter.h \ e-sorter-array.h \ + e-source-util.h \ e-stock-request.h \ e-text-event-processor-emacs-like.h \ e-text-event-processor-types.h \ @@ -102,11 +102,11 @@ libeutil_la_SOURCES = \ e-poolv.c \ e-plugin.c \ e-plugin-ui.c \ - e-plugin-util.c \ e-print.c \ e-selection.c \ e-sorter.c \ e-sorter-array.c \ + e-source-util.c \ e-stock-request.c \ e-text-event-processor-emacs-like.c \ e-text-event-processor.c \ diff --git a/e-util/e-plugin-util.c b/e-util/e-plugin-util.c deleted file mode 100644 index 7fd343d4b1..0000000000 --- a/e-util/e-plugin-util.c +++ /dev/null @@ -1,497 +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/> - * - * - * Copyright (C) 1999-2010 Novell, Inc. (www.novell.com) - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib/gi18n.h> -#include <gtk/gtk.h> -#include <libsoup/soup.h> -#include <libedataserver/e-source.h> -#include <string.h> - -#include "e-plugin-util.h" - -/* name of a property on a widget with corresponding property name for an ESource */ -#define EPU_SP_NAME "e-source-property-name" - -#define EPU_CHECK_TRUE "epu-check-true-value" -#define EPU_CHECK_FALSE "epu-check-false-value" - -static gboolean -epu_is_uri_proto (const gchar *uri, - const gchar *protocol) -{ - gboolean res; - - g_return_val_if_fail (uri != NULL, FALSE); - g_return_val_if_fail (protocol != NULL, FALSE); - - res = uri && g_ascii_strncasecmp (uri, protocol, strlen (protocol)) == 0; - - if (res) - res = strchr (protocol, ':') != NULL || uri[strlen (protocol)] == ':'; - - return res; -} - -/** - * e_plugin_util_is_source_proto: - * @source: #ESource object - * @protocol: protocol to check on, like "http", "https", ... - * - * Returns whether given source's uri is of the given protocol. - * - * Returns: whether given source's uri is of the given protocol. - **/ -gboolean -e_plugin_util_is_source_proto (ESource *source, - const gchar *protocol) -{ - gchar *uri; - gboolean res; - - g_return_val_if_fail (E_IS_SOURCE (source), FALSE); - g_return_val_if_fail (protocol != NULL, FALSE); - - uri = e_source_get_uri (source); - res = epu_is_uri_proto (uri, protocol); - g_free (uri); - - return res; -} - -/** - * e_plugin_util_is_group_proto: - * @group: #ESourceGroup object - * @protocol: protocol to check on, like "http", "https", ... - * - * Returns whether given groups' base uri is of the given protocol. - * - * Returns: whether given groups' base uri is of the given protocol. - **/ -gboolean -e_plugin_util_is_group_proto (ESourceGroup *group, - const gchar *protocol) -{ - g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE); - g_return_val_if_fail (protocol != NULL, FALSE); - - return epu_is_uri_proto (e_source_group_peek_base_uri (group), protocol); -} - -/** - * e_plugin_util_replace_at_sign: - * @str: string to work with - * - * Replaces all '@' with '%40' in @str. - * - * Returns: a newly-allocated string - **/ -gchar * -e_plugin_util_replace_at_sign (const gchar *str) -{ - gchar *res, *at; - - if (!str) - return NULL; - - res = g_strdup (str); - while (at = strchr (res, '@'), at) { - gchar *tmp = g_malloc0 (sizeof (gchar) * (1 + strlen (res) + 2)); - - strncpy (tmp, res, at - res); - strcat (tmp, "%40"); - strcat (tmp, at + 1); - - g_free (res); - res = tmp; - } - - return res; -} - -/** - * e_plugin_util_uri_no_proto: - * @uri: #SoupURI object - * - * Returns uri encoded as string, without protocol part. - * Returned pointer should be freed with g_free. - * - * Returns: uri encoded as string, without protocol part. - **/ -gchar * -e_plugin_util_uri_no_proto (SoupURI *uri) -{ - gchar *full_uri, *uri_noproto; - const gchar *tmp; - - g_return_val_if_fail (uri != NULL, NULL); - - full_uri = soup_uri_to_string (uri, FALSE); - g_return_val_if_fail (full_uri != NULL, NULL); - - tmp = strstr (full_uri, "://"); - if (tmp && tmp < strchr (full_uri, '/')) { - uri_noproto = g_strdup (tmp + 3); - } else { - uri_noproto = full_uri; - full_uri = NULL; - } - - g_free (full_uri); - - return uri_noproto; -} - -static void -epu_update_source_property (ESource *source, - GObject *object, - const gchar *value) -{ - const gchar *property_name; - - g_return_if_fail (E_IS_SOURCE (source)); - g_return_if_fail (G_IS_OBJECT (object)); - - property_name = g_object_get_data (object, EPU_SP_NAME); - g_return_if_fail (property_name != NULL); - - e_source_set_property (source, property_name, value); -} - -static void -epu_entry_changed_cb (GObject *entry, - ESource *source) -{ - g_return_if_fail (GTK_IS_ENTRY (entry)); - - epu_update_source_property (source, entry, gtk_entry_get_text (GTK_ENTRY (entry))); -} - -static void -epu_check_toggled_cb (GObject *button, - ESource *source) -{ - const gchar *true_value, *false_value; - - g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button)); - - true_value = g_object_get_data (button, EPU_CHECK_TRUE); - false_value = g_object_get_data (button, EPU_CHECK_FALSE); - - epu_update_source_property (source, button, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? true_value : false_value); -} - -/** - * e_plugin_util_add_entry: - * @parent: two-columns #GtkTable or #GtkContainer, where to add new entry - * @label: label for the entry; can be NULL for no label - * @source: #ESource object to which tight the entry change; can be NULL for no property binding - * @source_property: source's property name to use for a value; can be NULL for no property binding - * - * Adds a #GtkEntry to the table at the last row or to the container, with a given label. - * The entry will be always at the second column of the table. - * Value of an entry will be prefilled with a property value of the given - * source, and the source will be updated on any change of the entry automatically. - * Entry is shown by default. - * - * Returns: pointer to newly added #GtkEntry - **/ -GtkWidget * -e_plugin_util_add_entry (GtkWidget *parent, - const gchar *label, - ESource *source, - const gchar *source_property) -{ - GtkWidget *entry, *lbl = NULL; - const gchar *value; - gint row = -1; - - g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (GTK_IS_TABLE (parent) || GTK_IS_CONTAINER (parent), NULL); - - if (source || source_property) { - g_return_val_if_fail (E_IS_SOURCE (source), NULL); - g_return_val_if_fail (source_property != NULL, NULL); - g_return_val_if_fail (*source_property != 0, NULL); - } - - if (GTK_IS_TABLE (parent)) - g_object_get (parent, "n-rows", &row, NULL); - - if (label) { - lbl = gtk_label_new_with_mnemonic (label); - gtk_widget_show (lbl); - gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5); - if (row != -1) - gtk_table_attach (GTK_TABLE (parent), lbl, 0, 1, row, row + 1, GTK_FILL, 0, 0, 0); - else - gtk_container_add (GTK_CONTAINER (parent), lbl); - } - - if (source) - value = e_source_get_property (source, source_property); - else - value = NULL; - - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_entry_set_text (GTK_ENTRY (entry), value ? value : ""); - if (row != -1) - gtk_table_attach (GTK_TABLE (parent), entry, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - else - gtk_container_add (GTK_CONTAINER (parent), entry); - - if (lbl) - gtk_label_set_mnemonic_widget (GTK_LABEL (lbl), entry); - - if (source) { - g_object_set_data_full (G_OBJECT (entry), EPU_SP_NAME, g_strdup (source_property), g_free); - g_signal_connect ( - entry, "changed", - G_CALLBACK (epu_entry_changed_cb), source); - } - - return entry; -} - -/** - * e_plugin_util_add_check: - * @parent: either two-columns #GtkTable or #GtkContainer where to add new check box; or NULL to just create it - * @label: label for the check; cannot be NULL - * @source: #ESource object to which tight the check change; can be NULL for no property binding - * @source_property: source's property name to use for a value; can be NULL for no property binding - * @true_value: what value use for a checked state in a source - * @false_value: what value use for an unchecked state in a source - * - * Adds a #GtkCheckButton to the parent (if provided) at the last row, with a given label. - * The check will be always at the second column of the table. - * Value of a check will be prefilled with a property value of the given - * source, and the source will be updated on any change of the check automatically. - * Check is shown by default. - * - * Returns: pointer to newly added #GtkCheckButton - **/ -GtkWidget * -e_plugin_util_add_check (GtkWidget *parent, - const gchar *label, - ESource *source, - const gchar *source_property, - const gchar *true_value, - const gchar *false_value) -{ - GtkWidget *check; - const gchar *value; - guint row; - - g_return_val_if_fail (parent == NULL || GTK_IS_TABLE (parent) || GTK_IS_CONTAINER (parent), NULL); - g_return_val_if_fail (label != NULL, NULL); - - if (source || source_property) { - g_return_val_if_fail (source != NULL, NULL); - g_return_val_if_fail (E_IS_SOURCE (source), NULL); - g_return_val_if_fail (source_property != NULL, NULL); - g_return_val_if_fail (*source_property != 0, NULL); - } - - if (source) - value = e_source_get_property (source, source_property); - else - value = NULL; - - check = gtk_check_button_new_with_mnemonic (label); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), - value && (value == true_value || - (true_value && g_str_equal (value, true_value)) || - (!source && g_str_equal (value, "1")))); - gtk_widget_show (check); - - if (parent && GTK_IS_TABLE (parent)) { - g_object_get (parent, "n-rows", &row, NULL); - - gtk_table_attach (GTK_TABLE (parent), check, 1, 2, row , row + 1, GTK_FILL, 0, 0, 0); - } else if (parent) { - gtk_container_add (GTK_CONTAINER (parent), check); - } - - if (source) { - g_object_set_data_full (G_OBJECT (check), EPU_SP_NAME, g_strdup (source_property), g_free); - g_object_set_data_full (G_OBJECT (check), EPU_CHECK_TRUE, g_strdup (true_value), g_free); - g_object_set_data_full (G_OBJECT (check), EPU_CHECK_FALSE, g_strdup (false_value), g_free); - g_signal_connect ( - check, "toggled", - G_CALLBACK (epu_check_toggled_cb), source); - } - - return check; -} - -static void -epu_update_refresh_value (GtkWidget *spin, - GtkWidget *combobox, - ESource *source) -{ - gchar *value; - gint setting = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin)); - switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combobox))) { - case 0: - /* minutes */ - break; - case 1: - /* hours */ - setting *= 60; - break; - case 2: - /* days */ - setting *= 1440; - break; - case 3: - /* weeks */ - setting *= 10080; - break; - default: - g_warning ("%s: Time unit out of range", G_STRFUNC); - break; - } - - value = g_strdup_printf ("%d", setting); - epu_update_source_property (source, G_OBJECT (spin), value); - g_free (value); -} - -static void -epu_refresh_spin_changed_cb (GtkWidget *spin, - ESource *source) -{ - g_return_if_fail (spin != NULL); - g_return_if_fail (GTK_IS_SPIN_BUTTON (spin)); - - epu_update_refresh_value (spin, g_object_get_data (G_OBJECT (spin), "refresh-combo"), source); -} - -static void -epu_refresh_combo_changed_cb (GtkWidget *combobox, - ESource *source) -{ - g_return_if_fail (combobox != NULL); - g_return_if_fail (GTK_IS_COMBO_BOX (combobox)); - - epu_update_refresh_value (g_object_get_data (G_OBJECT (combobox), "refresh-spin"), combobox, source); -} - -/** - * e_plugin_util_add_refresh: - * @parent: two-columns #GtkTable where to add new "refresh" setup widgets or NULL to just create an hbox - * @label: label for the widgets; can be NULL, but for parent == NULL is ignored - * @source: #ESource object to which tight the refresh change; cannot be NULL - * @source_property: source's property name to use for a value; cannot be NULL - * - * Adds widgets to setup Refresh interval. The stored value is in minutes. - * Returns pointer to an HBox, which contains two widgets, spin and a combo box. - * Both can be accessed by g_object_get_data with a name "refresh-spin" and "refresh-combo". - * - * Returns: a new refresh control widget - **/ -GtkWidget * -e_plugin_util_add_refresh (GtkWidget *parent, - const gchar *label, - ESource *source, - const gchar *source_property) -{ - GtkWidget *lbl = NULL, *hbox, *spin, *combo; - const gchar *value; - gint row = -1, value_num, item_num = 0; - - g_return_val_if_fail (parent == NULL || GTK_IS_TABLE (parent), NULL); - g_return_val_if_fail (E_IS_SOURCE (source), NULL); - g_return_val_if_fail (source_property != NULL, NULL); - g_return_val_if_fail (*source_property != 0, NULL); - - if (parent) - g_object_get (parent, "n-rows", &row, NULL); - - value = e_source_get_property (source, source_property); - if (!value) { - value = "30"; - e_source_set_property (source, source_property, value); - } - - if (label && parent) { - lbl = gtk_label_new_with_mnemonic (label); - gtk_widget_show (lbl); - gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5); - gtk_table_attach (GTK_TABLE (parent), lbl, 0, 1, row, row + 1, GTK_FILL, 0, 0, 0); - } - - hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (hbox); - - spin = gtk_spin_button_new_with_range (0, 100, 1); - gtk_widget_show (spin); - gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, TRUE, 0); - - combo = gtk_combo_box_text_new (); - gtk_widget_show (combo); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("minutes")); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("hours")); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("days")); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("weeks")); - gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, TRUE, 0); - - value_num = value ? atoi (value) : 30; - - if (value_num && !(value_num % 10080)) { - /* weeks */ - item_num = 3; - value_num /= 10080; - } else if (value_num && !(value_num % 1440)) { - /* days */ - item_num = 2; - value_num /= 1440; - } else if (value_num && !(value_num % 60)) { - /* hours */ - item_num = 1; - value_num /= 60; - } - - gtk_combo_box_set_active (GTK_COMBO_BOX (combo), item_num); - gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), value_num); - - if (lbl) - gtk_label_set_mnemonic_widget (GTK_LABEL (lbl), spin); - - g_object_set_data_full (G_OBJECT (spin), EPU_SP_NAME, g_strdup (source_property), g_free); - - g_object_set_data (G_OBJECT (combo), "refresh-spin", spin); - g_object_set_data (G_OBJECT (spin), "refresh-combo", combo); - g_object_set_data (G_OBJECT (hbox), "refresh-spin", spin); - g_object_set_data (G_OBJECT (hbox), "refresh-combo", combo); - g_signal_connect ( - combo, "changed", - G_CALLBACK (epu_refresh_combo_changed_cb), source); - g_signal_connect ( - spin, "value-changed", - G_CALLBACK (epu_refresh_spin_changed_cb), source); - - if (parent) - gtk_table_attach (GTK_TABLE (parent), hbox, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - - return hbox; -} diff --git a/e-util/e-plugin-util.h b/e-util/e-plugin-util.h deleted file mode 100644 index de1b0b3487..0000000000 --- a/e-util/e-plugin-util.h +++ /dev/null @@ -1,45 +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: - * - * Copyright (C) 1999-2010 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_PLUGIN_UTIL_H -#define _E_PLUGIN_UTIL_H - -#include <gtk/gtk.h> - -#include <libsoup/soup.h> - -#include <libedataserver/e-source.h> -#include <libedataserver/e-source-group.h> - -gboolean e_plugin_util_is_source_proto (ESource *source, const gchar *protocol); -gboolean e_plugin_util_is_group_proto (ESourceGroup *group, const gchar *protocol); - -gchar *e_plugin_util_replace_at_sign (const gchar *str); -gchar *e_plugin_util_uri_no_proto (SoupURI *uri); - -/* common widgets used in plugin setup */ -GtkWidget *e_plugin_util_add_entry (GtkWidget *parent, const gchar *label, ESource *source, const gchar *source_property); -GtkWidget *e_plugin_util_add_check (GtkWidget *parent, const gchar *label, ESource *source, const gchar *source_property, const gchar *true_value, const gchar *false_value); - -/* multipack widgets */ -GtkWidget *e_plugin_util_add_refresh (GtkWidget *parent, const gchar *label, ESource *source, const gchar *source_property); - -#endif /* _E_PLUGIN_UTIL_H */ diff --git a/e-util/e-source-util.c b/e-util/e-source-util.c new file mode 100644 index 0000000000..61b7897d32 --- /dev/null +++ b/e-util/e-source-util.c @@ -0,0 +1,187 @@ +/* + * e-source-util.c + * + * 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/> + * + */ + +#include "e-source-util.h" + +typedef struct _AsyncContext AsyncContext; + +struct _AsyncContext { + EActivity *activity; + ESource *source; +}; + +static void +async_context_free (AsyncContext *context) +{ + if (context->activity != NULL) + g_object_unref (context->activity); + + if (context->source != NULL) + g_object_unref (context->source); + + g_slice_free (AsyncContext, context); +} + +static void +source_util_remove_cb (ESource *source, + GAsyncResult *result, + AsyncContext *context) +{ + EActivity *activity; + EAlertSink *alert_sink; + GError *error = NULL; + + activity = context->activity; + alert_sink = e_activity_get_alert_sink (activity); + + e_source_remove_finish (source, result, &error); + + if (e_activity_handle_cancellation (activity, error)) { + g_error_free (error); + + } else if (error != NULL) { + e_alert_submit ( + alert_sink, + "source:remove-source-fail", + e_source_get_display_name (context->source), + error->message, NULL); + g_error_free (error); + + } else { + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); + } + + async_context_free (context); +} + +/** + * e_source_util_remove: + * @source: the #ESource to be removed + * @alert_sink: an #EAlertSink + * + * Requests the D-Bus service to delete the key files for @source and all of + * its descendants and broadcast their removal to all clients. If an error + * occurs, an #EAlert will be posted to @alert_sink. + * + * This function does not block. The returned #EActivity can either be + * ignored or passed to something that can display activity status to the + * user, such as e_shell_backend_add_activity(). + * + * Returns: an #EActivity to track the operation + **/ +EActivity * +e_source_util_remove (ESource *source, + EAlertSink *alert_sink) +{ + AsyncContext *context; + GCancellable *cancellable; + + g_return_val_if_fail (E_IS_SOURCE (source), NULL); + g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL); + + cancellable = g_cancellable_new (); + + context = g_slice_new0 (AsyncContext); + context->activity = e_activity_new (); + context->source = g_object_ref (source); + + e_activity_set_alert_sink (context->activity, alert_sink); + e_activity_set_cancellable (context->activity, cancellable); + + e_source_remove ( + source, cancellable, (GAsyncReadyCallback) + source_util_remove_cb, context); + + g_object_unref (cancellable); + + return context->activity; +} + +static void +source_util_write_cb (ESource *source, + GAsyncResult *result, + AsyncContext *context) +{ + EActivity *activity; + EAlertSink *alert_sink; + GError *error = NULL; + + activity = context->activity; + alert_sink = e_activity_get_alert_sink (activity); + + e_source_write_finish (source, result, &error); + + if (e_activity_handle_cancellation (activity, error)) { + g_error_free (error); + + } else if (error != NULL) { + e_alert_submit ( + alert_sink, + "source:submit-data-fail", + error->message, NULL); + g_error_free (error); + + } else { + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); + } + + async_context_free (context); +} + +/** + * e_source_util_write: + * @source: an #ESource + * @alert_sink: an #EAlertSink + * + * Submits the current contents of @source to the D-Bus service to be + * written to disk and broadcast to other clients. If an error occurs, + * an #EAlert will be posted to @alert_sink. + * + * This function does not block. The returned #EActivity can either be + * ignored or passed to something that can display activity status to the + * user, such as e_shell_backend_add_activity(). + * + * Returns: an #EActivity to track the operation + **/ +EActivity * +e_source_util_write (ESource *source, + EAlertSink *alert_sink) +{ + AsyncContext *context; + GCancellable *cancellable; + + g_return_val_if_fail (E_IS_SOURCE (source), NULL); + g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL); + + cancellable = g_cancellable_new (); + + context = g_slice_new0 (AsyncContext); + context->activity = e_activity_new (); + + e_activity_set_alert_sink (context->activity, alert_sink); + e_activity_set_cancellable (context->activity, cancellable); + + e_source_write ( + source, cancellable, (GAsyncReadyCallback) + source_util_write_cb, context); + + g_object_unref (cancellable); + + return context->activity; +} + diff --git a/e-util/e-source-util.h b/e-util/e-source-util.h new file mode 100644 index 0000000000..589e91b13c --- /dev/null +++ b/e-util/e-source-util.h @@ -0,0 +1,42 @@ +/* + * e-source-util.h + * + * 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/> + * + */ + +/* These functions combine asynchronous ESource and ESourceRegistry methods + * with Evolution's EActivity and EAlert facilities to offer an easy-to-use, + * "fire-and-forget" API for ESource operations. Use these in situations + * where it's sufficient to just display an error message if the operation + * fails, and you don't need to operate on the result. */ + +#ifndef E_SOURCE_UTIL_H +#define E_SOURCE_UTIL_H + +#include <libedataserver/e-source.h> + +#include <e-util/e-activity.h> +#include <libevolution-utils/e-alert-sink.h> + +G_BEGIN_DECLS + +EActivity * e_source_util_remove (ESource *source, + EAlertSink *alert_sink); +EActivity * e_source_util_write (ESource *source, + EAlertSink *alert_sink); + +G_END_DECLS + +#endif /* E_SOURCE_UTIL_H */ diff --git a/e-util/e-util.c b/e-util/e-util.c index 715735110c..38c1b85244 100644 --- a/e-util/e-util.c +++ b/e-util/e-util.c @@ -53,7 +53,6 @@ #include <camel/camel.h> #include <libedataserver/e-data-server-util.h> #include <libedataserver/e-categories.h> -#include <libedataserver/e-source-list.h> #include "filter/e-filter-option.h" @@ -1334,31 +1333,6 @@ e_util_get_searchable_categories (void) } /** - * e_util_set_source_combo_box_list: - * @source_combo_box: an #ESourceComboBox - * @source_gconf_path: GConf path with sources to use in an #ESourceList - * - * Sets an #ESourceList of a given GConf path to an #ESourceComboBox. - **/ -void -e_util_set_source_combo_box_list (GtkWidget *source_combo_box, - const gchar *source_gconf_path) -{ - ESourceList *source_list; - GConfClient *gconf_client; - - g_return_if_fail (source_combo_box != NULL); - g_return_if_fail (source_gconf_path != NULL); - - gconf_client = gconf_client_get_default (); - source_list = e_source_list_new_for_gconf ( - gconf_client, source_gconf_path); - g_object_set (source_combo_box, "source-list", source_list, NULL); - g_object_unref (source_list); - g_object_unref (gconf_client); -} - -/** * e_binding_transform_color_to_string: * @binding: a #GBinding * @source_value: a #GValue of type #GDK_TYPE_COLOR @@ -1435,7 +1409,7 @@ e_binding_transform_string_to_color (GBinding *binding, * @binding: a #GBinding * @source_value: a #GValue of type #E_TYPE_SOURCE * @target_value: a #GValue of type #G_TYPE_STRING - * @source_list: an #ESourceList + * @registry: an #ESourceRegistry * * Transforms an #ESource object to its UID string. * @@ -1445,14 +1419,14 @@ gboolean e_binding_transform_source_to_uid (GBinding *binding, const GValue *source_value, GValue *target_value, - ESourceList *source_list) + ESourceRegistry *registry) { ESource *source; const gchar *string; gboolean success = FALSE; g_return_val_if_fail (G_IS_BINDING (binding), FALSE); - g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), FALSE); + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE); source = g_value_get_object (source_value); if (E_IS_SOURCE (source)) { @@ -1469,34 +1443,34 @@ e_binding_transform_source_to_uid (GBinding *binding, * @binding: a #GBinding * @source_value: a #GValue of type #G_TYPE_STRING * @target_value: a #GValue of type #E_TYPE_SOURCe - * @source_list: an #ESourceList + * @registry: an #ESourceRegistry * * Transforms an #ESource UID string to the corresponding #ESource object - * in @source_list. + * in @registry. * - * Returns: %TRUE if @source_list had an #ESource object with a matching + * Returns: %TRUE if @registry had an #ESource object with a matching * UID string **/ gboolean e_binding_transform_uid_to_source (GBinding *binding, const GValue *source_value, GValue *target_value, - ESourceList *source_list) + ESourceRegistry *registry) { ESource *source; const gchar *string; gboolean success = FALSE; g_return_val_if_fail (G_IS_BINDING (binding), FALSE); - g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), FALSE); + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE); string = g_value_get_string (source_value); if (string == NULL || *string == '\0') return FALSE; - source = e_source_list_peek_source_by_uid (source_list, string); + source = e_source_registry_ref_source (registry, string); if (source != NULL) { - g_value_set_object (target_value, source); + g_value_take_object (target_value, source); success = TRUE; } diff --git a/e-util/e-util.h b/e-util/e-util.h index bd9ad2dc05..af2232489e 100644 --- a/e-util/e-util.h +++ b/e-util/e-util.h @@ -32,7 +32,7 @@ #include <e-util/e-marshal.h> #include <e-util/e-util-enums.h> -#include <libedataserver/e-source-list.h> +#include <libedataserver/e-source-registry.h> /* e_get_user_data_dir() used to live here, so #include its new home * for backward-compatibility (not that we really care about that). */ @@ -131,10 +131,6 @@ GSList * e_util_get_category_filter_options (void); GList * e_util_get_searchable_categories (void); -void e_util_set_source_combo_box_list - (GtkWidget *source_combo_box, - const gchar *source_gconf_path); - /* Useful GBinding transform functions */ gboolean e_binding_transform_color_to_string (GBinding *binding, @@ -150,12 +146,12 @@ gboolean e_binding_transform_source_to_uid (GBinding *binding, const GValue *source_value, GValue *target_value, - ESourceList *source_list); + ESourceRegistry *registry); gboolean e_binding_transform_uid_to_source (GBinding *binding, const GValue *source_value, GValue *target_value, - ESourceList *source_list); + ESourceRegistry *registry); G_END_DECLS diff --git a/libemail-utils/e-account-utils.c b/libemail-utils/e-account-utils.c deleted file mode 100644 index 6e64d45747..0000000000 --- a/libemail-utils/e-account-utils.c +++ /dev/null @@ -1,252 +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/> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -/** - * SECTION: e-account-utils - * @include: e-util/e-account-utils.h - **/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-account-utils.h" - -#include <string.h> -#include <gconf/gconf-client.h> - -static EAccountList *global_account_list; - -static gboolean -account_has_transport_url (EAccount *account) -{ - return (account != NULL) && - (account->enabled) && - (account->transport != NULL) && - (account->transport->url != NULL) && - (account->transport->url[0] != '\0'); -} - -/** - * e_get_account_list: - * - * Returns the global #EAccountList. - * - * Returns: the global #EAccountList - **/ -EAccountList * -e_get_account_list (void) -{ - if (G_UNLIKELY (global_account_list == NULL)) { - GConfClient *client; - - client = gconf_client_get_default (); - global_account_list = e_account_list_new (client); - g_object_unref (client); - } - - g_return_val_if_fail (global_account_list != NULL, NULL); - - return global_account_list; -} - -/** - * e_get_default_account: - * - * Returns the #EAccount marked as the default mail account. - * - * Returns: the default #EAccount - **/ -EAccount * -e_get_default_account (void) -{ - EAccountList *account_list; - const EAccount *account; - - account_list = e_get_account_list (); - account = e_account_list_get_default (account_list); - - /* XXX EAccountList misuses const. */ - return (EAccount *) account; -} - -/** - * e_set_default_account: - * @account: an #EAccount - * - * Marks @account as the default mail account. - **/ -void -e_set_default_account (EAccount *account) -{ - EAccountList *account_list; - - g_return_if_fail (E_IS_ACCOUNT (account)); - - account_list = e_get_account_list (); - e_account_list_set_default (account_list, account); -} - -/** - * e_get_account_by_name: - * @name: a mail account name - * - * Returns the #EAccount with the given name, or %NULL if no such - * account exists. - * - * Returns: an #EAccount having the given account name, or %NULL - **/ -EAccount * -e_get_account_by_name (const gchar *name) -{ - EAccountList *account_list; - const EAccount *account; - e_account_find_t find; - - g_return_val_if_fail (name != NULL, NULL); - - find = E_ACCOUNT_FIND_NAME; - account_list = e_get_account_list (); - account = e_account_list_find (account_list, find, name); - - /* XXX EAccountList misuses const. */ - return (EAccount *) account; -} - -/** - * e_get_account_by_uid: - * @uid: a mail account UID - * - * Returns the #EAccount corresponding to the given unique identity (UID), - * or %NULL if no such account exists. The @uid can refer to an #EAccount - * UID, a #CamelStore UID, or even a #CamelTransport UID. - * - * Returns: the corresponding #EAccount, or %NULL - **/ -EAccount * -e_get_account_by_uid (const gchar *uid) -{ - EAccountList *account_list; - const EAccount *account; - e_account_find_t find; - gchar *account_uid; - - g_return_val_if_fail (uid != NULL, NULL); - - /* EAccounts have the following invariant: - * - * CamelStore UID == EAccount UID - * CamelTransport UID == EAccount UID + "-transport" - * - * Therefore we can detect CamelTransport UIDs and convert them. - */ - if (g_str_has_suffix (uid, "-transport")) - account_uid = g_strndup (uid, strlen (uid) - 10); - else - account_uid = g_strdup (uid); - - find = E_ACCOUNT_FIND_UID; - account_list = e_get_account_list (); - account = e_account_list_find (account_list, find, account_uid); - - g_free (account_uid); - - /* XXX EAccountList misuses const. */ - return (EAccount *) account; -} - -/** - * e_get_any_enabled_account: - * - * Returns the default mail account if it's enabled, otherwise the first - * enabled mail account in the global #EAccountList, or finally %NULL if - * all mail accounts are disabled or none exist. - * - * Returns: an enabled #EAccount, or %NULL if there are none - **/ -EAccount * -e_get_any_enabled_account (void) -{ - EAccount *account; - EAccountList *account_list; - EIterator *iter; - - account = e_get_default_account (); - if (account != NULL && account->enabled) - return account; - - account = NULL; - - account_list = e_get_account_list (); - iter = e_list_get_iterator (E_LIST (account_list)); - - while (e_iterator_is_valid (iter) && account == NULL) { - EAccount *candidate; - - /* XXX EIterator misuses const. */ - candidate = (EAccount *) e_iterator_get (iter); - - if (candidate->enabled) - account = candidate; - else - e_iterator_next (iter); - } - - g_object_unref (iter); - - return account; -} - -/** - * e_get_default_transport: - * - * Returns transport information for the default account if it's enabled and - * has transport information, or else from the first enabled mail account in - * the global #EAccountList that has transport information, or finally %NULL - * if no transport information could be found. - * - * Returns: an #EAccount with transport info, or %NULL - **/ -EAccount * -e_get_default_transport (void) -{ - EAccountList *account_list; - EAccount *account; - EIterator *iterator; - - account = e_get_default_account (); - if (account_has_transport_url (account)) - return account; - - account_list = e_get_account_list (); - iterator = e_list_get_iterator (E_LIST (account_list)); - - while (e_iterator_is_valid (iterator)) { - /* XXX EIterator misuses const. */ - account = (EAccount *) e_iterator_get (iterator); - if (account_has_transport_url (account)) { - g_object_unref (iterator); - return account; - } - e_iterator_next (iterator); - } - - g_object_unref (iterator); - - return NULL; -} - diff --git a/libemail-utils/e-account-utils.h b/libemail-utils/e-account-utils.h deleted file mode 100644 index d7dbd283fd..0000000000 --- a/libemail-utils/e-account-utils.h +++ /dev/null @@ -1,37 +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/> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -#ifndef E_ACCOUNT_UTILS_H -#define E_ACCOUNT_UTILS_H - -#include <camel/camel.h> -#include <libedataserver/e-account.h> -#include <libedataserver/e-account-list.h> - -G_BEGIN_DECLS - -EAccountList * e_get_account_list (void); -EAccount * e_get_default_account (void); -void e_set_default_account (EAccount *account); -EAccount * e_get_account_by_name (const gchar *name); -EAccount * e_get_account_by_uid (const gchar *uid); -EAccount * e_get_any_enabled_account (void); -EAccount * e_get_default_transport (void); - -G_END_DECLS - -#endif /* E_ACCOUNT_UTILS_H */ diff --git a/libemail-utils/e-signature-list.c b/libemail-utils/e-signature-list.c deleted file mode 100644 index 5be5d31ca1..0000000000 --- a/libemail-utils/e-signature-list.c +++ /dev/null @@ -1,501 +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: - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-signature-list.h" - -#include <string.h> - -#include <libedataserver/e-uid.h> - -#define E_SIGNATURE_LIST_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_SIGNATURE_LIST, ESignatureListPrivate)) - -struct _ESignatureListPrivate { - GConfClient *gconf; - guint notify_id; - gboolean resave; -}; - -enum { - SIGNATURE_ADDED, - SIGNATURE_CHANGED, - SIGNATURE_REMOVED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE ( - ESignatureList, - e_signature_list, - E_TYPE_LIST) - -static void -e_signature_list_dispose (GObject *object) -{ - ESignatureList *list = (ESignatureList *) object; - - if (list->priv->gconf) { - if (list->priv->notify_id != 0) - gconf_client_notify_remove ( - list->priv->gconf, list->priv->notify_id); - g_object_unref (list->priv->gconf); - list->priv->gconf = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_signature_list_parent_class)->dispose (object); -} - -static void -e_signature_list_class_init (ESignatureListClass *class) -{ - GObjectClass *object_class; - - g_type_class_add_private (class, sizeof (ESignatureListPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = e_signature_list_dispose; - - signals[SIGNATURE_ADDED] = g_signal_new ( - "signature-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESignatureListClass, signature_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_SIGNATURE); - - signals[SIGNATURE_CHANGED] = g_signal_new ( - "signature-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESignatureListClass, signature_changed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_SIGNATURE); - - signals[SIGNATURE_REMOVED] = g_signal_new ( - "signature-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESignatureListClass, signature_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_SIGNATURE); -} - -static void -e_signature_list_init (ESignatureList *signature_list) -{ - signature_list->priv = E_SIGNATURE_LIST_GET_PRIVATE (signature_list); -} - -static GSList * -add_autogen (ESignatureList *list, - GSList *new_sigs) -{ - ESignature *autogen; - - autogen = e_signature_new (); - e_signature_set_autogenerated (autogen, TRUE); - - e_list_append (E_LIST (list), autogen); - - return g_slist_prepend (new_sigs, autogen); -} - -static void -gconf_signatures_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data) -{ - ESignatureList *signature_list = user_data; - GSList *list, *l, *n, *new_sigs = NULL; - gboolean have_autogen = FALSE; - gboolean resave = FALSE; - ESignature *signature; - EList *old_sigs; - EIterator *iter; - gboolean found; - gchar *uid; - - old_sigs = e_list_duplicate (E_LIST (signature_list)); - - list = gconf_client_get_list ( - client, "/apps/evolution/mail/signatures", - GCONF_VALUE_STRING, NULL); - for (l = list; l; l = l->next) { - found = FALSE; - if ((uid = e_signature_uid_from_xml (l->data))) { - /* See if this is an existing signature */ - iter = e_list_get_iterator (old_sigs); - while (e_iterator_is_valid (iter)) { - const gchar *signature_uid; - - signature = (ESignature *) e_iterator_get (iter); - signature_uid = e_signature_get_uid (signature); - if (!strcmp (signature_uid, uid)) { - /* The signature still exists, so remove - * it from "old_sigs" and update it. */ - found = TRUE; - e_iterator_delete (iter); - if (e_signature_set_from_xml ( - signature, l->data)) - g_signal_emit ( - signature_list, - signals[SIGNATURE_CHANGED], - 0, signature); - - have_autogen |= - e_signature_get_autogenerated ( - signature); - - break; - } - - e_iterator_next (iter); - } - - g_object_unref (iter); - } - - if (!found) { - resave = TRUE; - - /* Must be a new signature */ - signature = e_signature_new_from_xml (l->data); - if (signature) { - have_autogen |= - e_signature_get_autogenerated (signature); - - e_list_append (E_LIST (signature_list), signature); - new_sigs = g_slist_prepend (new_sigs, signature); - } - } - - g_free (uid); - } - - g_slist_foreach (list, (GFunc) g_free, NULL); - g_slist_free (list); - - if (!have_autogen) { - new_sigs = add_autogen (signature_list, new_sigs); - resave = TRUE; - } - - if (new_sigs != NULL) { - /* Now emit signals for each added signature. */ - l = g_slist_reverse (new_sigs); - while (l != NULL) { - n = l->next; - signature = l->data; - g_signal_emit ( - signature_list, - signals[SIGNATURE_ADDED], 0, - signature); - g_object_unref (signature); - g_slist_free_1 (l); - l = n; - } - } - - /* Anything left in old_sigs must have been deleted */ - iter = e_list_get_iterator (old_sigs); - while (e_iterator_is_valid (iter)) { - signature = (ESignature *) e_iterator_get (iter); - e_list_remove (E_LIST (signature_list), signature); - g_signal_emit ( - signature_list, signals[SIGNATURE_REMOVED], 0, - signature); - e_iterator_next (iter); - } - - g_object_unref (iter); - g_object_unref (old_sigs); - - signature_list->priv->resave = resave; -} - -static gpointer -copy_func (gconstpointer data, - gpointer closure) -{ - GObject *object = (GObject *) data; - - g_object_ref (object); - - return object; -} - -static void -free_func (gpointer data, - gpointer closure) -{ - g_object_unref (data); -} - -/** - * e_signature_list_new: - * - * Reads the list of signaturess from @gconf and listens for changes. - * Will emit #signature_added, #signature_changed, and #signature_removed - * signals according to notifications from GConf. - * - * You can modify the list using e_list_append(), e_list_remove(), and - * e_iterator_delete(). After adding, removing, or changing accounts, - * you must call e_signature_list_save() to push the changes back to - * GConf. - * - * Return value: the list of signatures - **/ -ESignatureList * -e_signature_list_new (void) -{ - ESignatureList *signature_list; - GConfClient *client; - - signature_list = g_object_new (E_TYPE_SIGNATURE_LIST, NULL); - - client = gconf_client_get_default (); - e_signature_list_construct (signature_list, client); - g_object_unref (client); - - return signature_list; -} - -void -e_signature_list_construct (ESignatureList *signature_list, - GConfClient *gconf) -{ - g_return_if_fail (GCONF_IS_CLIENT (gconf)); - - e_list_construct (E_LIST (signature_list), copy_func, free_func, NULL); - signature_list->priv->gconf = gconf; - g_object_ref (gconf); - - gconf_client_add_dir (signature_list->priv->gconf, - "/apps/evolution/mail/signatures", - GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); - - signature_list->priv->notify_id = - gconf_client_notify_add (signature_list->priv->gconf, - "/apps/evolution/mail/signatures", - gconf_signatures_changed, signature_list, - NULL, NULL); - - gconf_signatures_changed (signature_list->priv->gconf, - signature_list->priv->notify_id, - NULL, signature_list); - - if (signature_list->priv->resave) { - e_signature_list_save (signature_list); - signature_list->priv->resave = FALSE; - } -} - -/** - * e_signature_list_save: - * @signature_list: an #ESignatureList - * - * Saves @signature_list to GConf. Signals will be emitted for changes. - **/ -void -e_signature_list_save (ESignatureList *signature_list) -{ - GSList *list = NULL; - ESignature *signature; - EIterator *iter; - gchar *xmlbuf; - - for (iter = e_list_get_iterator (E_LIST (signature_list)); - e_iterator_is_valid (iter); - e_iterator_next (iter)) { - signature = (ESignature *) e_iterator_get (iter); - - if ((xmlbuf = e_signature_to_xml (signature))) - list = g_slist_append (list, xmlbuf); - } - - g_object_unref (iter); - - gconf_client_set_list (signature_list->priv->gconf, - "/apps/evolution/mail/signatures", - GCONF_VALUE_STRING, list, NULL); - - while (list) { - g_free (list->data); - list = g_slist_remove (list, list->data); - } - - gconf_client_suggest_sync (signature_list->priv->gconf, NULL); -} - -/** - * e_signature_list_add: - * @signature_list: signature list - * @signature: signature to add - * - * Add an signature to the signature list. Will emit the signature-changed - * event. - **/ -void -e_signature_list_add (ESignatureList *signature_list, - ESignature *signature) -{ - e_list_append ((EList *) signature_list, signature); - g_signal_emit (signature_list, signals[SIGNATURE_ADDED], 0, signature); -} - -/** - * e_signature_list_change: - * @signature_list: signature list - * @signature: signature to change - * - * Signal that the details of an signature have changed. - **/ -void -e_signature_list_change (ESignatureList *signature_list, - ESignature *signature) -{ - /* maybe the signature should do this itself ... */ - g_signal_emit (signature_list, signals[SIGNATURE_CHANGED], 0, signature); -} - -/** - * e_signature_list_remove: - * @signature_list: signature list - * @signature: signature - * - * Remove an signature from the signature list, and emit the - * signature-removed signal. If the signature was the default signature, - * then reset the default to the first signature. - **/ -void -e_signature_list_remove (ESignatureList *signature_list, - ESignature *signature) -{ - /* not sure if need to ref but no harm */ - g_object_ref (signature); - e_list_remove ((EList *) signature_list, signature); - g_signal_emit (signature_list, signals[SIGNATURE_REMOVED], 0, signature); - g_object_unref (signature); -} - -/** - * e_signature_list_find_by_name: - * @signature_list: an #ESignatureList - * @name: the signature name to find - * - * Searches @signature_list for the given signature name. - * - * Returns: the matching signature or %NULL if it doesn't exist - **/ -ESignature * -e_signature_list_find_by_name (ESignatureList *signature_list, - const gchar *signature_name) -{ - ESignature *signature = NULL; - EIterator *it; - - g_return_val_if_fail (E_IS_SIGNATURE_LIST (signature_list), NULL); - - /* this could use a callback for more flexibility ... - * ... but this makes the common cases easier */ - - if (signature_name == NULL) - return NULL; - - for (it = e_list_get_iterator (E_LIST (signature_list)); - e_iterator_is_valid (it); - e_iterator_next (it)) { - const gchar *value; - - /* XXX EIterator misuses const. */ - signature = (ESignature *) e_iterator_get (it); - value = e_signature_get_name (signature); - - if (g_strcmp0 (value, signature_name) == 0) - break; - - signature = NULL; - } - - g_object_unref (it); - - return signature; -} - -/** - * e_signature_list_find_by_uid: - * @signature_list: an #ESignatureList - * @name: the signature UID to find - * - * Searches @signature_list for the given signature UID. - * - * Returns: the matching signature or %NULL if it doesn't exist - **/ -ESignature * -e_signature_list_find_by_uid (ESignatureList *signature_list, - const gchar *signature_uid) -{ - ESignature *signature = NULL; - EIterator *it; - - g_return_val_if_fail (E_IS_SIGNATURE_LIST (signature_list), NULL); - - /* this could use a callback for more flexibility ... - * ... but this makes the common cases easier */ - - if (signature_uid == NULL) - return NULL; - - for (it = e_list_get_iterator (E_LIST (signature_list)); - e_iterator_is_valid (it); - e_iterator_next (it)) { - const gchar *value = NULL; - - /* XXX EIterator misuses const. */ - signature = (ESignature *) e_iterator_get (it); - value = e_signature_get_uid (signature); - - if (g_strcmp0 (value, signature_uid) == 0) - break; - - signature = NULL; - } - - g_object_unref (it); - - return signature; -} diff --git a/libemail-utils/e-signature-list.h b/libemail-utils/e-signature-list.h deleted file mode 100644 index ebcb4b28e2..0000000000 --- a/libemail-utils/e-signature-list.h +++ /dev/null @@ -1,91 +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: - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_SIGNATURE_LIST_H -#define E_SIGNATURE_LIST_H - -#include <gconf/gconf-client.h> -#include <libedataserver/e-list.h> -#include <libemail-utils/e-signature.h> - -/* Standard GObject macros */ -#define E_TYPE_SIGNATURE_LIST \ - (e_signature_list_get_type ()) -#define E_SIGNATURE_LIST(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_SIGNATURE_LIST, ESignatureList)) -#define E_SIGNATURE_LIST_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_SIGNATURE_LIST, ESignatureListClass)) -#define E_IS_SIGNATURE_LIST(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_SIGNATURE_LIST)) -#define E_IS_SIGNATURE_LIST_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_SIGNATURE_LIST)) -#define E_SIGNATURE_LIST_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_SIGNATURE_LIST, ESignatureListClass)) - -G_BEGIN_DECLS - -typedef struct _ESignatureList ESignatureList; -typedef struct _ESignatureListClass ESignatureListClass; -typedef struct _ESignatureListPrivate ESignatureListPrivate; - -struct _ESignatureList { - EList parent; - ESignatureListPrivate *priv; -}; - -struct _ESignatureListClass { - EListClass parent_class; - - /* Signals */ - void (*signature_added) (ESignatureList *signature_list, - ESignature *signature); - void (*signature_changed) (ESignatureList *signature_list, - ESignature *signature); - void (*signature_removed) (ESignatureList *signature_list, - ESignature *signature); -}; - -GType e_signature_list_get_type (void); -ESignatureList *e_signature_list_new (void); -void e_signature_list_construct (ESignatureList *signature_list, - GConfClient *client); -void e_signature_list_save (ESignatureList *signature_list); -void e_signature_list_add (ESignatureList *signature_list, - ESignature *signature); -void e_signature_list_change (ESignatureList *signature_list, - ESignature *signature); -void e_signature_list_remove (ESignatureList *signature_list, - ESignature *signature); -ESignature * e_signature_list_find_by_name (ESignatureList *signature_list, - const gchar *signature_name); -ESignature * e_signature_list_find_by_uid (ESignatureList *signature_list, - const gchar *signature_uid); - -G_END_DECLS - -#endif /* E_SIGNATURE_LIST_H */ diff --git a/libemail-utils/e-signature-utils.c b/libemail-utils/e-signature-utils.c deleted file mode 100644 index ca46f053db..0000000000 --- a/libemail-utils/e-signature-utils.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * e-signature-utils.c - * - * 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/> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-signature-utils.h" - -#include <errno.h> -#include <camel/camel.h> -#include <glib/gstdio.h> - -#ifndef G_OS_WIN32 -#include <sys/wait.h> -#endif - -#include <libedataserver/e-data-server-util.h> - -static ESignatureList *global_signature_list; - -ESignatureList * -e_get_signature_list (void) -{ - if (G_UNLIKELY (global_signature_list == NULL)) - global_signature_list = e_signature_list_new (); - - g_return_val_if_fail (global_signature_list != NULL, NULL); - - return global_signature_list; -} - -ESignature * -e_get_signature_by_name (const gchar *name) -{ - ESignatureList *signature_list; - - g_return_val_if_fail (name != NULL, NULL); - - signature_list = e_get_signature_list (); - - return e_signature_list_find_by_name (signature_list, name); -} - -ESignature * -e_get_signature_by_uid (const gchar *uid) -{ - ESignatureList *signature_list; - - g_return_val_if_fail (uid != NULL, NULL); - - signature_list = e_get_signature_list (); - - return e_signature_list_find_by_uid (signature_list, uid); -} - -gchar * -e_create_signature_file (GError **error) -{ - const gchar *data_dir; - gchar basename[32]; - gchar *filename; - gchar *pathname; - gint32 ii; - - data_dir = e_get_user_data_dir (); - pathname = g_build_filename (data_dir, "signatures", NULL); - filename = NULL; - - if (g_mkdir_with_parents (pathname, 0700) < 0) { - g_set_error ( - error, G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s: %s", pathname, g_strerror (errno)); - g_free (pathname); - return NULL; - } - - for (ii = 0; ii < G_MAXINT32; ii++) { - - g_snprintf ( - basename, sizeof (basename), - "signature-%" G_GINT32_FORMAT, ii); - - g_free (filename); - filename = g_build_filename (pathname, basename, NULL); - - if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { - gint fd; - - fd = g_creat (filename, 0600); - if (fd >= 0) { - close (fd); - break; - } - - /* If we failed once we're probably going - * to continue failing, so just give up. */ - g_set_error ( - error, G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s: %s", filename, g_strerror (errno)); - g_free (filename); - filename = NULL; - break; - } - } - - /* If there are actually G_MAXINT32 signature files, the - * most recent signature file we be overwritten. Sorry. */ - - return filename; -} - -gchar * -e_read_signature_file (ESignature *signature, - gboolean convert_to_html, - GError **error) -{ - CamelStream *input_stream; - CamelStream *output_stream; - GByteArray *buffer; - const gchar *filename; - gboolean is_html; - gchar *content; - gsize length; - gint fd; - - g_return_val_if_fail (E_IS_SIGNATURE (signature), NULL); - - filename = e_signature_get_filename (signature); - is_html = e_signature_get_is_html (signature); - - fd = g_open (filename, O_RDONLY, 0); - if (fd < 0) { - g_set_error ( - error, G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s: %s", filename, g_strerror (errno)); - return NULL; - } - - input_stream = camel_stream_fs_new_with_fd (fd); - - if (!is_html && convert_to_html) { - CamelStream *filtered_stream; - CamelMimeFilter *filter; - gint32 flags; - - filtered_stream = - camel_stream_filter_new (input_stream); - g_object_unref (input_stream); - - flags = - CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT | - CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | - CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES | - CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES; - filter = camel_mime_filter_tohtml_new (flags, 0); - camel_stream_filter_add ( - CAMEL_STREAM_FILTER (filtered_stream), filter); - g_object_unref (filter); - - input_stream = filtered_stream; - } - - buffer = g_byte_array_new (); - output_stream = camel_stream_mem_new (); - camel_stream_mem_set_byte_array ( - CAMEL_STREAM_MEM (output_stream), buffer); - camel_stream_write_to_stream (input_stream, output_stream, NULL, NULL); - g_object_unref (output_stream); - g_object_unref (input_stream); - - /* Make sure the buffer is nul-terminated. */ - length = (gsize) buffer->len; - g_byte_array_append (buffer, (guint8 *) "", 1); - content = (gchar *) g_byte_array_free (buffer, FALSE); - - /* Signatures are saved as UTF-8, but we still need to check that - * the signature is valid UTF-8 because the user may be opening - * a signature file that is in his/her locale character set. If - * it's not in UTF-8 then try converting from the current locale. */ - if (!g_utf8_validate (content, length, NULL)) { - gchar *utf8; - - utf8 = g_locale_to_utf8 (content, length, NULL, NULL, error); - g_free (content); - content = utf8; - } - - return content; -} - -gchar * -e_run_signature_script (const gchar *filename) -{ - /* FIXME Make this cross-platform, prefer GLib functions over - * POSIX, and report errors via GError instead of dumping - * messages to the terminal where users won't see them. */ - -#ifndef G_OS_WIN32 - gint in_fds[2]; - pid_t pid; - - g_return_val_if_fail (filename != NULL, NULL); - - if (pipe (in_fds) == -1) { - g_warning ( - "Failed to create pipe to '%s': %s", - filename, g_strerror (errno)); - return NULL; - } - - pid = fork (); - - /* Child Process */ - if (pid == 0) { - gint maxfd, ii; - - close (in_fds[0]); - if (dup2 (in_fds[1], STDOUT_FILENO) < 0) - _exit (255); - close (in_fds[1]); - - setsid (); - - maxfd = sysconf (_SC_OPEN_MAX); - for (ii = 3; ii < maxfd; ii++) { - if (ii == STDIN_FILENO) - continue; - if (ii == STDOUT_FILENO) - continue; - if (ii == STDERR_FILENO) - continue; - fcntl (ii, F_SETFD, FD_CLOEXEC); - } - - execlp ("/bin/sh", "/bin/sh", "-c", filename, NULL); - - g_warning ( - "Could not execute '%s': %s", - filename, g_strerror (errno)); - - _exit (255); - - /* Parent Process */ - } else if (pid > 0) { - CamelStream *output_stream; - CamelStream *input_stream; - GByteArray *buffer; - gchar *content; - gsize length; - gint result; - gint status; - - close (in_fds[1]); - - buffer = g_byte_array_new (); - output_stream = camel_stream_mem_new (); - camel_stream_mem_set_byte_array ( - CAMEL_STREAM_MEM (output_stream), buffer); - - input_stream = camel_stream_fs_new_with_fd (in_fds[0]); - camel_stream_write_to_stream ( - input_stream, output_stream, NULL, NULL); - g_object_unref (input_stream); - - g_object_unref (output_stream); - - /* Make sure the buffer is nul-terminated. */ - length = (gsize) buffer->len; - g_byte_array_append (buffer, (guchar *) "", 1); - content = (gchar *) g_byte_array_free (buffer, FALSE); - - /* Signature scripts are supposed to generate UTF-8 content, - * but because users are known to never read the manual, we - * try to do our best if the content isn't valid UTF-8 by - * assuming that the content is in the user's locale - * character set. */ - if (!g_utf8_validate (content, length, NULL)) { - gchar *utf8; - - /* XXX Should pass a GError here. */ - utf8 = g_locale_to_utf8 ( - content, length, NULL, NULL, NULL); - g_free (content); - content = utf8; - } - - /* Wait for the script process to terminate. */ - result = waitpid (pid, &status, 0); - - if (result == -1 && errno == EINTR) { - /* Child process is hanging... */ - kill (pid, SIGTERM); - sleep (1); - result = waitpid (pid, &status, WNOHANG); - if (result == 0) { - /* ...still hanging, set phasers to KILL. */ - kill (pid, SIGKILL); - sleep (1); - waitpid (pid, &status, WNOHANG); - } - } - - return content; - - /* Forking Failed */ - } else { - g_warning ( - "Failed to create child process '%s': %s", - filename, g_strerror (errno)); - close (in_fds[0]); - close (in_fds[1]); - } -#endif - - return NULL; -} diff --git a/libemail-utils/e-signature-utils.h b/libemail-utils/e-signature-utils.h deleted file mode 100644 index a642a136f1..0000000000 --- a/libemail-utils/e-signature-utils.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * e-signature-utils.h - * - * 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/> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -#ifndef E_SIGNATURE_UTILS_H -#define E_SIGNATURE_UTILS_H - -#include <gtk/gtk.h> -#include <libemail-utils/e-signature.h> -#include <libemail-utils/e-signature-list.h> - -G_BEGIN_DECLS - -ESignatureList *e_get_signature_list (void); -ESignature * e_get_signature_by_name (const gchar *name); -ESignature * e_get_signature_by_uid (const gchar *uid); -gchar * e_create_signature_file (GError **error); -gchar * e_read_signature_file (ESignature *signature, - gboolean convert_to_html, - GError **error); -gchar * e_run_signature_script (const gchar *filename); - -G_END_DECLS - -#endif /* E_SIGNATURE_UTILS_H */ diff --git a/libemail-utils/e-signature.c b/libemail-utils/e-signature.c deleted file mode 100644 index e568c63bd2..0000000000 --- a/libemail-utils/e-signature.c +++ /dev/null @@ -1,749 +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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/xmlmemory.h> - -#include <glib/gi18n-lib.h> - -#include <libedataserver/e-uid.h> -#include <libedataserver/e-data-server-util.h> - -#include "e-signature.h" - -#define E_SIGNATURE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_SIGNATURE, ESignaturePrivate)) - -struct _ESignaturePrivate { - gchar *filename; - gchar *name; - gchar *uid; - - gboolean autogenerated; - gboolean is_html; - gboolean is_script; -}; - -enum { - PROP_0, - PROP_AUTOGENERATED, - PROP_FILENAME, - PROP_IS_HTML, - PROP_IS_SCRIPT, - PROP_NAME, - PROP_UID -}; - -G_DEFINE_TYPE ( - ESignature, - e_signature, - G_TYPE_OBJECT) - -static gboolean -xml_set_bool (xmlNodePtr node, - const gchar *name, - gboolean *val) -{ - gboolean v_boolean; - gchar *buf; - - if ((buf = (gchar *) xmlGetProp (node, (xmlChar *) name))) { - v_boolean = (!strcmp (buf, "true") || !strcmp (buf, "yes")); - xmlFree (buf); - - if (v_boolean != *val) { - *val = v_boolean; - return TRUE; - } - } - - return FALSE; -} - -static gboolean -xml_set_prop (xmlNodePtr node, - const gchar *name, - gchar **val) -{ - gchar *buf, *new_val; - - buf = (gchar *) xmlGetProp (node, (xmlChar *) name); - new_val = g_strdup (buf); - xmlFree (buf); - - /* We can use strcmp here whether the value is UTF8 or - * not, since we only care if the bytes changed. - */ - if (!*val || strcmp (*val, new_val)) { - g_free (*val); - *val = new_val; - return TRUE; - } else { - g_free (new_val); - return FALSE; - } -} - -static gboolean -xml_set_content (xmlNodePtr node, - gchar **val) -{ - gchar *buf, *new_val; - - buf = (gchar *) xmlNodeGetContent (node); - new_val = g_strdup (buf); - xmlFree (buf); - - /* We can use strcmp here whether the value is UTF8 or - * not, since we only care if the bytes changed. */ - if (!*val || strcmp (*val, new_val)) { - g_free (*val); - *val = new_val; - return TRUE; - } else { - g_free (new_val); - return FALSE; - } -} - -static void -signature_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_AUTOGENERATED: - e_signature_set_autogenerated ( - E_SIGNATURE (object), - g_value_get_boolean (value)); - return; - - case PROP_FILENAME: - e_signature_set_filename ( - E_SIGNATURE (object), - g_value_get_string (value)); - return; - - case PROP_IS_HTML: - e_signature_set_is_html ( - E_SIGNATURE (object), - g_value_get_boolean (value)); - return; - - case PROP_IS_SCRIPT: - e_signature_set_is_script ( - E_SIGNATURE (object), - g_value_get_boolean (value)); - return; - - case PROP_NAME: - e_signature_set_name ( - E_SIGNATURE (object), - g_value_get_string (value)); - return; - - case PROP_UID: - e_signature_set_uid ( - E_SIGNATURE (object), - g_value_get_string (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -signature_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_AUTOGENERATED: - g_value_set_boolean ( - value, e_signature_get_autogenerated ( - E_SIGNATURE (object))); - return; - - case PROP_FILENAME: - g_value_set_string ( - value, e_signature_get_filename ( - E_SIGNATURE (object))); - return; - - case PROP_IS_HTML: - g_value_set_boolean ( - value, e_signature_get_is_html ( - E_SIGNATURE (object))); - return; - - case PROP_IS_SCRIPT: - g_value_set_boolean ( - value, e_signature_get_is_script ( - E_SIGNATURE (object))); - return; - - case PROP_NAME: - g_value_set_string ( - value, e_signature_get_name ( - E_SIGNATURE (object))); - return; - - case PROP_UID: - g_value_set_string ( - value, e_signature_get_uid ( - E_SIGNATURE (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -signature_finalize (GObject *object) -{ - ESignaturePrivate *priv; - - priv = E_SIGNATURE (object)->priv; - - g_free (priv->filename); - g_free (priv->name); - g_free (priv->uid); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_signature_parent_class)->finalize (object); -} - -static void -e_signature_class_init (ESignatureClass *class) -{ - GObjectClass *object_class; - - g_type_class_add_private (class, sizeof (ESignaturePrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = signature_set_property; - object_class->get_property = signature_get_property; - object_class->finalize = signature_finalize; - - g_object_class_install_property ( - object_class, - PROP_AUTOGENERATED, - g_param_spec_boolean ( - "autogenerated", - "Autogenerated", - NULL, - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_FILENAME, - g_param_spec_string ( - "filename", - "Filename", - NULL, - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_IS_HTML, - g_param_spec_boolean ( - "is-html", - "Is HTML", - NULL, - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_IS_SCRIPT, - g_param_spec_boolean ( - "is-script", - "Is Script", - NULL, - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_NAME, - g_param_spec_string ( - "name", - "Name", - NULL, - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_UID, - g_param_spec_string ( - "uid", - "UID", - NULL, - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); -} - -static void -e_signature_init (ESignature *signature) -{ - signature->priv = E_SIGNATURE_GET_PRIVATE (signature); -} - -/** - * e_signature_new: - * - * Returns a new signature which can be filled in and - * added to an #ESignatureList. - * - * Returns: a new #ESignature - **/ -ESignature * -e_signature_new (void) -{ - ESignature *signature; - - signature = g_object_new (E_TYPE_SIGNATURE, NULL); - signature->priv->uid = e_uid_new (); - - return signature; -} - -/** - * e_signature_new_from_xml: - * @xml: an XML signature description - * - * Return value: a new #ESignature based on the data in @xml, or %NULL - * if @xml could not be parsed as valid signature data. - **/ -ESignature * -e_signature_new_from_xml (const gchar *xml) -{ - ESignature *signature; - - signature = g_object_new (E_TYPE_SIGNATURE, NULL); - - if (!e_signature_set_from_xml (signature, xml)) { - g_object_unref (signature); - return NULL; - } - - return signature; -} - -/** - * e_signature_uid_from_xml: - * @xml: an XML signature description - * - * Return value: the permanent UID of the signature described by @xml - * (or %NULL if @xml could not be parsed or did not contain a uid). - * The caller must free this string. - **/ -gchar * -e_signature_uid_from_xml (const gchar *xml) -{ - xmlNodePtr node; - xmlDocPtr doc; - gchar *uid = NULL; - - if (!(doc = xmlParseDoc ((xmlChar *) xml))) - return NULL; - - node = doc->children; - if (strcmp ((gchar *)node->name, "signature") != 0) { - xmlFreeDoc (doc); - return NULL; - } - - xml_set_prop (node, "uid", &uid); - xmlFreeDoc (doc); - - return uid; -} - -/** - * e_signature_set_from_xml: - * @signature: an #ESignature - * @xml: an XML signature description. - * - * Changes @signature to match @xml. - * - * Returns: %TRUE if the signature was loaded or %FALSE otherwise - **/ -gboolean -e_signature_set_from_xml (ESignature *signature, - const gchar *xml) -{ - gboolean changed = FALSE; - xmlNodePtr node, cur; - xmlDocPtr doc; - gboolean bool; - gchar *buf; - - if (!(doc = xmlParseDoc ((xmlChar *) xml))) - return FALSE; - - node = doc->children; - if (strcmp ((gchar *)node->name, "signature") != 0) { - xmlFreeDoc (doc); - return FALSE; - } - - buf = NULL; - xml_set_prop (node, "uid", &buf); - - if (buf && *buf) { - g_free (signature->priv->uid); - signature->priv->uid = buf; - } - - changed |= xml_set_prop (node, "name", &signature->priv->name); - changed |= xml_set_bool (node, "auto", &signature->priv->autogenerated); - - if (e_signature_get_autogenerated (signature)) { - xmlFreeDoc (doc); - - return changed; - } - - buf = NULL; - xml_set_prop (node, "format", &buf); - if (buf && !strcmp (buf, "text/html")) - bool = TRUE; - else - bool = FALSE; - g_free (buf); - - if (e_signature_get_is_html (signature) != bool) { - e_signature_set_is_html (signature, bool); - changed = TRUE; - } - - cur = node->children; - while (cur) { - if (!strcmp ((gchar *)cur->name, "filename")) { - changed |= xml_set_content ( - cur, &signature->priv->filename); - changed |= xml_set_bool ( - cur, "script", &signature->priv->is_script); - break; - } else if (!strcmp ((gchar *)cur->name, "script")) { - /* this is for handling 1.4 signature script definitions */ - changed |= xml_set_content ( - cur, &signature->priv->filename); - if (!e_signature_get_is_script (signature)) { - e_signature_set_is_script (signature, TRUE); - changed = TRUE; - } - break; - } - cur = cur->next; - } - - /* If the signature is not a script, replace the directory - * part with the current signatures directory. This makes - * moving the signatures directory transparent. */ - if (!e_signature_get_is_script (signature)) { - const gchar *user_data_dir; - gchar *basename; - gchar *filename; - - user_data_dir = e_get_user_data_dir (); - - filename = signature->priv->filename; - basename = g_path_get_basename (filename); - signature->priv->filename = g_build_filename ( - user_data_dir, "signatures", basename, NULL); - g_free (basename); - g_free (filename); - } - - xmlFreeDoc (doc); - - return changed; -} - -/** - * e_signature_to_xml: - * @signature: an #ESignature - * - * Return value: an XML representation of @signature, which the caller - * must free. - **/ -gchar * -e_signature_to_xml (ESignature *signature) -{ - xmlChar *xmlbuf; - gchar *tmp; - xmlNodePtr root, node; - xmlDocPtr doc; - const gchar *string; - gint n; - - doc = xmlNewDoc ((xmlChar *) "1.0"); - - root = xmlNewDocNode (doc, NULL, (xmlChar *) "signature", NULL); - xmlDocSetRootElement (doc, root); - - string = e_signature_get_name (signature); - xmlSetProp (root, (xmlChar *) "name", (xmlChar *) string); - - string = e_signature_get_uid (signature); - xmlSetProp (root, (xmlChar *) "uid", (xmlChar *) string); - - if (e_signature_get_autogenerated (signature)) - string = "true"; - else - string = "false"; - xmlSetProp (root, (xmlChar *) "auto", (xmlChar *) string); - - if (!e_signature_get_autogenerated (signature)) { - if (e_signature_get_is_html (signature)) - string = "text/html"; - else - string = "text/plain"; - xmlSetProp (root, (xmlChar *) "format", (xmlChar *) string); - - string = e_signature_get_filename (signature); - if (string != NULL) { - - /* For scripts we save the full filename, - * for normal signatures just the basename. */ - if (e_signature_get_is_script (signature)) { - node = xmlNewTextChild ( - root, NULL, (xmlChar *) "filename", - (xmlChar *) string); - xmlSetProp ( - node, (xmlChar *) "script", - (xmlChar *) "true"); - } else { - gchar *basename; - - basename = g_path_get_basename (string); - node = xmlNewTextChild ( - root, NULL, (xmlChar *) "filename", - (xmlChar *) basename); - g_free (basename); - } - } - } else { - /* this is to make Evolution-1.4 and older 1.5 versions happy */ - xmlSetProp (root, (xmlChar *) "format", (xmlChar *) "text/html"); - } - - xmlDocDumpMemory (doc, &xmlbuf, &n); - xmlFreeDoc (doc); - - /* remap to glib memory */ - tmp = g_malloc (n + 1); - memcpy (tmp, xmlbuf, n); - tmp[n] = '\0'; - xmlFree (xmlbuf); - - return tmp; -} - -gboolean -e_signature_is_equal (ESignature *signature1, - ESignature *signature2) -{ - const gchar *uid1; - const gchar *uid2; - - g_return_val_if_fail (E_IS_SIGNATURE (signature1), FALSE); - g_return_val_if_fail (E_IS_SIGNATURE (signature2), FALSE); - - /* XXX Simply compares the UIDs. Not fool-proof. */ - uid1 = e_signature_get_uid (signature1); - uid2 = e_signature_get_uid (signature2); - - return (g_strcmp0 (uid1, uid2) == 0); -} - -gboolean -e_signature_get_autogenerated (ESignature *signature) -{ - g_return_val_if_fail (E_IS_SIGNATURE (signature), FALSE); - - return signature->priv->autogenerated; -} - -void -e_signature_set_autogenerated (ESignature *signature, - gboolean autogenerated) -{ - g_return_if_fail (E_IS_SIGNATURE (signature)); - - if (signature->priv->autogenerated == autogenerated) - return; - - signature->priv->autogenerated = autogenerated; - - /* Autogenerated flags overrides several properties. */ - g_object_freeze_notify (G_OBJECT (signature)); - g_object_notify (G_OBJECT (signature), "autogenerated"); - g_object_notify (G_OBJECT (signature), "filename"); - g_object_notify (G_OBJECT (signature), "is-html"); - g_object_notify (G_OBJECT (signature), "is-script"); - g_object_notify (G_OBJECT (signature), "name"); - g_object_thaw_notify (G_OBJECT (signature)); -} - -const gchar * -e_signature_get_filename (ESignature *signature) -{ - g_return_val_if_fail (E_IS_SIGNATURE (signature), NULL); - - /* Autogenerated flags overrides the filename property. */ - if (e_signature_get_autogenerated (signature)) - return NULL; - - return signature->priv->filename; -} - -void -e_signature_set_filename (ESignature *signature, - const gchar *filename) -{ - g_return_if_fail (E_IS_SIGNATURE (signature)); - - g_free (signature->priv->filename); - signature->priv->filename = g_strdup (filename); - - g_object_notify (G_OBJECT (signature), "filename"); -} - -gboolean -e_signature_get_is_html (ESignature *signature) -{ - g_return_val_if_fail (E_IS_SIGNATURE (signature), FALSE); - - /* Autogenerated flag overrides the is-html property. */ - if (e_signature_get_autogenerated (signature)) - return FALSE; - - return signature->priv->is_html; -} - -void -e_signature_set_is_html (ESignature *signature, - gboolean is_html) -{ - g_return_if_fail (E_IS_SIGNATURE (signature)); - - if (signature->priv->is_html == is_html) - return; - - signature->priv->is_html = is_html; - - g_object_notify (G_OBJECT (signature), "is-html"); -} - -gboolean -e_signature_get_is_script (ESignature *signature) -{ - g_return_val_if_fail (E_IS_SIGNATURE (signature), FALSE); - - /* Autogenerated flags overrides the is-script property. */ - if (e_signature_get_autogenerated (signature)) - return FALSE; - - return signature->priv->is_script; -} - -void -e_signature_set_is_script (ESignature *signature, - gboolean is_script) -{ - g_return_if_fail (E_IS_SIGNATURE (signature)); - - if (signature->priv->is_script == is_script) - return; - - signature->priv->is_script = is_script; - - g_object_notify (G_OBJECT (signature), "is-script"); -} - -const gchar * -e_signature_get_name (ESignature *signature) -{ - g_return_val_if_fail (E_IS_SIGNATURE (signature), NULL); - - /* Autogenerated flag overrides the name property. */ - if (e_signature_get_autogenerated (signature)) - return _("Autogenerated"); - - return signature->priv->name; -} - -void -e_signature_set_name (ESignature *signature, - const gchar *name) -{ - g_return_if_fail (E_IS_SIGNATURE (signature)); - - g_free (signature->priv->name); - signature->priv->name = g_strdup (name); - - g_object_notify (G_OBJECT (signature), "name"); -} - -const gchar * -e_signature_get_uid (ESignature *signature) -{ - g_return_val_if_fail (E_IS_SIGNATURE (signature), NULL); - - return signature->priv->uid; -} - -void -e_signature_set_uid (ESignature *signature, - const gchar *uid) -{ - g_return_if_fail (E_IS_SIGNATURE (signature)); - - g_free (signature->priv->uid); - - if (uid == NULL) - signature->priv->uid = e_uid_new (); - else - signature->priv->uid = g_strdup (uid); - - g_object_notify (G_OBJECT (signature), "uid"); -} diff --git a/libemail-utils/e-signature.h b/libemail-utils/e-signature.h deleted file mode 100644 index fad1faffa3..0000000000 --- a/libemail-utils/e-signature.h +++ /dev/null @@ -1,90 +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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_SIGNATURE_H -#define E_SIGNATURE_H - -#include <glib-object.h> - -/* Standard GObject macros */ -#define E_TYPE_SIGNATURE \ - (e_signature_get_type ()) -#define E_SIGNATURE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_SIGNATURE, ESignature)) -#define E_SIGNATURE_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_SIGNATURE, ESignatureClass)) -#define E_IS_SIGNATURE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_SIGNATURE)) -#define E_IS_SIGNATURE_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_SIGNATURE)) -#define E_SIGNATURE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_SIGNATURE, ESignatureClass)) - -G_BEGIN_DECLS - -typedef struct _ESignature ESignature; -typedef struct _ESignatureClass ESignatureClass; -typedef struct _ESignaturePrivate ESignaturePrivate; - -struct _ESignature { - GObject parent; - ESignaturePrivate *priv; -}; - -struct _ESignatureClass { - GObjectClass parent_class; -}; - -GType e_signature_get_type (void); -ESignature * e_signature_new (void); -ESignature * e_signature_new_from_xml (const gchar *xml); -gchar * e_signature_uid_from_xml (const gchar *xml); -gboolean e_signature_set_from_xml (ESignature *signature, - const gchar *xml); -gchar * e_signature_to_xml (ESignature *signature); -gboolean e_signature_is_equal (ESignature *signature1, - ESignature *signature2); -gboolean e_signature_get_autogenerated (ESignature *signature); -void e_signature_set_autogenerated (ESignature *signature, - gboolean autogenerated); -const gchar * e_signature_get_filename (ESignature *signature); -void e_signature_set_filename (ESignature *signature, - const gchar *filename); -gboolean e_signature_get_is_html (ESignature *signature); -void e_signature_set_is_html (ESignature *signature, - gboolean is_html); -gboolean e_signature_get_is_script (ESignature *signature); -void e_signature_set_is_script (ESignature *signature, - gboolean is_script); -const gchar * e_signature_get_name (ESignature *signature); -void e_signature_set_name (ESignature *signature, - const gchar *name); -const gchar * e_signature_get_uid (ESignature *signature); -void e_signature_set_uid (ESignature *signature, - const gchar *uid); - -G_END_DECLS - -#endif /* E_SIGNATURE_H */ diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index c09a78f70c..bb3c662d5c 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -5,7 +5,6 @@ widgetsincludedir = $(privincludedir)/misc ui_DATA = e-send-options.ui widgetsinclude_HEADERS = \ - e-account-combo-box.h \ e-action-combo-box.h \ e-activity-bar.h \ e-activity-proxy.h \ @@ -38,6 +37,9 @@ widgetsinclude_HEADERS = \ e-image-chooser.h \ e-import-assistant.h \ e-interval-chooser.h \ + e-mail-account-manager.h \ + e-mail-account-tree-view.h \ + e-mail-identity-combo-box.h \ e-map.h \ e-menu-tool-action.h \ e-menu-tool-button.h \ @@ -93,7 +95,6 @@ libemiscwidgets_la_CPPFLAGS = \ libemiscwidgets_la_SOURCES = \ $(widgetsinclude_HEADERS) \ - e-account-combo-box.c \ e-action-combo-box.c \ e-activity-bar.c \ e-activity-proxy.c \ @@ -126,6 +127,9 @@ libemiscwidgets_la_SOURCES = \ e-image-chooser.c \ e-import-assistant.c \ e-interval-chooser.c \ + e-mail-account-manager.c \ + e-mail-account-tree-view.c \ + e-mail-identity-combo-box.c \ e-map.c \ e-menu-tool-action.c \ e-menu-tool-button.c \ diff --git a/widgets/misc/e-account-combo-box.c b/widgets/misc/e-account-combo-box.c deleted file mode 100644 index 9c750f9ec4..0000000000 --- a/widgets/misc/e-account-combo-box.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - * e-account-combo-box.c - * - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-account-combo-box.h" - -#include <string.h> - -#define E_ACCOUNT_COMBO_BOX_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBoxPrivate)) - -enum { - COLUMN_STRING, - COLUMN_ACCOUNT -}; - -enum { - REFRESHED, - LAST_SIGNAL -}; - -struct _EAccountComboBoxPrivate { - EAccountList *account_list; - GHashTable *index; - gint num_displayed_accounts; -}; - -static CamelSession *camel_session; -static guint signal_ids[LAST_SIGNAL]; - -G_DEFINE_TYPE ( - EAccountComboBox, - e_account_combo_box, - GTK_TYPE_COMBO_BOX) - -static gboolean -account_combo_box_has_dupes (GList *list, - const gchar *address) -{ - GList *iter; - guint count = 0; - - /* Look for duplicates of the given email address. */ - for (iter = list; iter != NULL; iter = iter->next) { - EAccount *account = iter->data; - - if (g_ascii_strcasecmp (account->id->address, address) == 0) - count++; - } - - return (count > 1); -} - -static EAccount * -account_combo_box_choose_account (EAccountComboBox *combo_box) -{ - EAccountList *account_list; - EAccount *account; - GtkTreeModel *model; - GtkTreeIter iter; - - account_list = e_account_combo_box_get_account_list (combo_box); - g_return_val_if_fail (account_list != NULL, NULL); - - /* First try the default account. */ - - /* XXX EAccountList misuses const. */ - account = (EAccount *) - e_account_list_get_default (account_list); - - /* If there is no default account, give up. */ - if (account == NULL) - return NULL; - - /* Make sure the default account appears in the combo box. */ - if (g_hash_table_lookup (combo_box->priv->index, account) != NULL) - return account; - - /* Default account is disabled or otherwise unusable, - * so fall back to the first account in the combo box. */ - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); - - if (!gtk_tree_model_get_iter_first (model, &iter)) - return NULL; - - gtk_tree_model_get (model, &iter, COLUMN_ACCOUNT, &account, -1); - - return account; -} - -static gboolean -account_combo_box_test_account (EAccount *account) -{ - CamelService *service; - gboolean writable = FALSE; - - /* Account must be enabled. */ - if (!account->enabled) - return FALSE; - - /* Account must have a non-empty email address. */ - if (account->id->address == NULL || *account->id->address == '\0') - return FALSE; - - /* XXX Not sure I understand this part. */ - if (account->parent_uid == NULL) - return TRUE; - - /* Account must be writable. */ - service = camel_session_get_service (camel_session, account->uid); - if (CAMEL_IS_STORE (service)) { - CamelStore *store = CAMEL_STORE (service); - writable = (store->mode & CAMEL_STORE_WRITE); - } - - return writable; -} - -static void -account_combo_box_refresh_cb (EAccountList *account_list, - EAccount *unused, - EAccountComboBox *combo_box) -{ - GtkListStore *store; - GtkTreeModel *model; - EIterator *account_iter; - EAccount *account; - GHashTable *index; - GList *list = NULL; - GList *iter; - - combo_box->priv->num_displayed_accounts = 0; - - store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_ACCOUNT); - model = GTK_TREE_MODEL (store); - index = combo_box->priv->index; - - g_hash_table_remove_all (index); - - if (account_list == NULL) - goto skip; - - /* Build a list of EAccounts to display. */ - account_iter = e_list_get_iterator (E_LIST (account_list)); - while (e_iterator_is_valid (account_iter)) { - EAccount *account; - - /* XXX EIterator misuses const. */ - account = (EAccount *) e_iterator_get (account_iter); - if (account_combo_box_test_account (account)) - list = g_list_prepend (list, account); - e_iterator_next (account_iter); - } - g_object_unref (account_iter); - - list = g_list_reverse (list); - - /* Populate the list store and index. */ - for (iter = list; iter != NULL; iter = iter->next) { - GtkTreeRowReference *reference; - GtkTreeIter tree_iter; - GtkTreePath *path; - gchar *string; - - account = iter->data; - combo_box->priv->num_displayed_accounts++; - - /* Show the account name for duplicate email addresses. */ - if (account_combo_box_has_dupes (list, account->id->address)) - string = g_strdup_printf ( - "%s <%s> (%s)", - account->id->name, - account->id->address, - account->name); - else - string = g_strdup_printf ( - "%s <%s>", - account->id->name, - account->id->address); - - gtk_list_store_append (store, &tree_iter); - gtk_list_store_set ( - store, &tree_iter, - COLUMN_STRING, string, - COLUMN_ACCOUNT, account, -1); - - path = gtk_tree_model_get_path (model, &tree_iter); - reference = gtk_tree_row_reference_new (model, path); - g_hash_table_insert (index, account, reference); - gtk_tree_path_free (path); - - g_free (string); - } - - g_list_free (list); - -skip: - /* Restore the previously selected account. */ - account = e_account_combo_box_get_active (combo_box); - if (account != NULL) - g_object_ref (account); - gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), model); - e_account_combo_box_set_active (combo_box, account); - if (account != NULL) - g_object_unref (account); - - g_signal_emit (combo_box, signal_ids[REFRESHED], 0); -} - -static GObject * -account_combo_box_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - GObject *object; - GObjectClass *parent_class; - GtkCellRenderer *renderer; - - /* Chain up to parent's constructor() method. */ - parent_class = G_OBJECT_CLASS (e_account_combo_box_parent_class); - object = parent_class->constructor ( - type, n_construct_properties, construct_properties); - - renderer = gtk_cell_renderer_text_new (); - - gtk_cell_layout_pack_start ( - GTK_CELL_LAYOUT (object), renderer, TRUE); - gtk_cell_layout_add_attribute ( - GTK_CELL_LAYOUT (object), renderer, "text", COLUMN_STRING); - - return object; -} - -static void -account_combo_box_dispose (GObject *object) -{ - EAccountComboBoxPrivate *priv; - - priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (object); - - if (priv->account_list != NULL) { - g_signal_handlers_disconnect_by_func ( - priv->account_list, - account_combo_box_refresh_cb, object); - g_object_unref (priv->account_list); - priv->account_list = NULL; - } - - g_hash_table_remove_all (priv->index); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_account_combo_box_parent_class)->dispose (object); -} - -static void -account_combo_box_finalize (GObject *object) -{ - EAccountComboBoxPrivate *priv; - - priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (object); - - g_hash_table_destroy (priv->index); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_account_combo_box_parent_class)->finalize (object); -} - -static void -e_account_combo_box_class_init (EAccountComboBoxClass *class) -{ - GObjectClass *object_class; - - g_type_class_add_private (class, sizeof (EAccountComboBoxPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->constructor = account_combo_box_constructor; - object_class->dispose = account_combo_box_dispose; - object_class->finalize = account_combo_box_finalize; - - signal_ids[REFRESHED] = g_signal_new ( - "refreshed", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -e_account_combo_box_init (EAccountComboBox *combo_box) -{ - GHashTable *index; - - /* Reverse-lookup index */ - index = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) g_object_unref, - (GDestroyNotify) gtk_tree_row_reference_free); - - combo_box->priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (combo_box); - combo_box->priv->index = index; -} - -GtkWidget * -e_account_combo_box_new (void) -{ - return g_object_new (E_TYPE_ACCOUNT_COMBO_BOX, NULL); -} - -void -e_account_combo_box_set_session (CamelSession *session) -{ - /* XXX Really gross hack. - * - * We need a CamelSession to test whether a given EAccount is - * writable. The global CamelSession object is defined in the - * mailer, but we're too far down the stack to access it. So - * we have to rely on someone passing us a reference to it. - * - * A much cleaner solution would be to store the writeability - * of an account directly into the EAccount, but this would likely - * require breaking ABI and all the fun that goes along with that. - */ - - camel_session = session; -} - -EAccountList * -e_account_combo_box_get_account_list (EAccountComboBox *combo_box) -{ - g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), NULL); - - return combo_box->priv->account_list; -} - -void -e_account_combo_box_set_account_list (EAccountComboBox *combo_box, - EAccountList *account_list) -{ - EAccountComboBoxPrivate *priv; - - g_return_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box)); - - if (account_list != NULL) - g_return_if_fail (E_IS_ACCOUNT_LIST (account_list)); - - priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (combo_box); - - if (priv->account_list != NULL) { - g_signal_handlers_disconnect_by_func ( - priv->account_list, - account_combo_box_refresh_cb, combo_box); - g_object_unref (priv->account_list); - priv->account_list = NULL; - } - - if (account_list != NULL) { - priv->account_list = g_object_ref (account_list); - - /* Listen for changes to the account list. */ - g_signal_connect ( - priv->account_list, "account-added", - G_CALLBACK (account_combo_box_refresh_cb), combo_box); - g_signal_connect ( - priv->account_list, "account-changed", - G_CALLBACK (account_combo_box_refresh_cb), combo_box); - g_signal_connect ( - priv->account_list, "account-removed", - G_CALLBACK (account_combo_box_refresh_cb), combo_box); - } - - account_combo_box_refresh_cb (account_list, NULL, combo_box); -} - -EAccount * -e_account_combo_box_get_active (EAccountComboBox *combo_box) -{ - EAccount *account; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean iter_set; - - g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), NULL); - - iter_set = gtk_combo_box_get_active_iter ( - GTK_COMBO_BOX (combo_box), &iter); - if (!iter_set) - return NULL; - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); - gtk_tree_model_get (model, &iter, COLUMN_ACCOUNT, &account, -1); - - return account; -} - -gboolean -e_account_combo_box_set_active (EAccountComboBox *combo_box, - EAccount *account) -{ - EAccountList *account_list; - GtkTreeRowReference *reference; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - gboolean iter_set; - - g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), FALSE); - - if (account != NULL) - g_return_val_if_fail (E_IS_ACCOUNT (account), FALSE); - - account_list = combo_box->priv->account_list; - g_return_val_if_fail (account_list != NULL, FALSE); - - /* NULL means choose an account ourselves. */ - if (account == NULL) - account = account_combo_box_choose_account (combo_box); - - if (account == NULL) - return FALSE; - - /* Lookup the tree row reference for the account. */ - reference = g_hash_table_lookup (combo_box->priv->index, account); - if (reference == NULL) - return FALSE; - - /* Convert the reference to a tree iterator. */ - path = gtk_tree_row_reference_get_path (reference); - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); - iter_set = gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - - if (!iter_set) - return FALSE; - - /* Activate the corresponding combo box item. */ - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter); - - return TRUE; -} - -const gchar * -e_account_combo_box_get_active_name (EAccountComboBox *combo_box) -{ - EAccount *account; - - g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), NULL); - - account = e_account_combo_box_get_active (combo_box); - return (account != NULL) ? account->name : NULL; -} - -gboolean -e_account_combo_box_set_active_name (EAccountComboBox *combo_box, - const gchar *account_name) -{ - EAccountList *account_list; - EAccount *account; - - g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), FALSE); - - account_list = combo_box->priv->account_list; - g_return_val_if_fail (account_list != NULL, FALSE); - - /* XXX EAccountList misuses const. */ - account = (EAccount *) e_account_list_find ( - account_list, E_ACCOUNT_FIND_NAME, account_name); - - if (account == NULL) - return FALSE; - - return e_account_combo_box_set_active (combo_box, account); -} - -/** - * e_account_combo_box_count_displayed_accounts: - * @combo_box: an #EAccountComboBox - * - * Counts the number of accounts that are displayed in the @combo_box. This may not - * be the actual number of accounts that are configured, as some of those accounts - * may be disabled by the user. - * - * Return value: number of active and valid accounts as shown in the @combo_box. - */ -gint -e_account_combo_box_count_displayed_accounts (EAccountComboBox *combo_box) -{ - g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), -1); - - return combo_box->priv->num_displayed_accounts; -} diff --git a/widgets/misc/e-account-combo-box.h b/widgets/misc/e-account-combo-box.h deleted file mode 100644 index aa29c97306..0000000000 --- a/widgets/misc/e-account-combo-box.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * e-account-combo-box.h - * - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_ACCOUNT_COMBO_BOX_H -#define E_ACCOUNT_COMBO_BOX_H - -#include <gtk/gtk.h> -#include <camel/camel.h> -#include <libedataserver/e-account.h> -#include <libedataserver/e-account-list.h> - -/* Standard GObject macros */ -#define E_TYPE_ACCOUNT_COMBO_BOX \ - (e_account_combo_box_get_type ()) -#define E_ACCOUNT_COMBO_BOX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBox)) -#define E_ACCOUNT_COMBO_BOX_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBoxClass)) -#define E_IS_ACCOUNT_COMBO_BOX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_ACCOUNT_COMBO_BOX)) -#define E_IS_ACCOUNT_COMBO_BOX_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_ACCOUNT_COMBO_BOX)) -#define E_ACCOUNT_COMBO_BOX_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_ACCOUNT_COMBO_BOX, EAccountComboBoxClass)) - -G_BEGIN_DECLS - -typedef struct _EAccountComboBox EAccountComboBox; -typedef struct _EAccountComboBoxClass EAccountComboBoxClass; -typedef struct _EAccountComboBoxPrivate EAccountComboBoxPrivate; - -struct _EAccountComboBox { - GtkComboBox parent; - EAccountComboBoxPrivate *priv; -}; - -struct _EAccountComboBoxClass { - GtkComboBoxClass parent_class; -}; - -GType e_account_combo_box_get_type (void); -GtkWidget * e_account_combo_box_new (void); -void e_account_combo_box_set_session (CamelSession *session); -EAccountList * e_account_combo_box_get_account_list - (EAccountComboBox *combo_box); -void e_account_combo_box_set_account_list - (EAccountComboBox *combo_box, - EAccountList *account_list); -EAccount * e_account_combo_box_get_active (EAccountComboBox *combo_box); -gboolean e_account_combo_box_set_active (EAccountComboBox *combo_box, - EAccount *account); -const gchar * e_account_combo_box_get_active_name - (EAccountComboBox *combo_box); -gboolean e_account_combo_box_set_active_name - (EAccountComboBox *combo_box, - const gchar *account_name); -gint e_account_combo_box_count_displayed_accounts - (EAccountComboBox *combo_box); - -G_END_DECLS - -#endif /* E_ACCOUNT_COMBO_BOX_H */ diff --git a/widgets/misc/e-mail-account-manager.c b/widgets/misc/e-mail-account-manager.c new file mode 100644 index 0000000000..fd5e999a90 --- /dev/null +++ b/widgets/misc/e-mail-account-manager.c @@ -0,0 +1,384 @@ +/* + * e-mail-account-manager.c + * + * 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/> + * + */ + +#include "e-mail-account-manager.h" + +#include <config.h> +#include <glib/gi18n-lib.h> +#include <gdk/gdkkeysyms.h> + +#include "e-mail-account-tree-view.h" + +#define E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerPrivate)) + +struct _EMailAccountManagerPrivate { + ESourceRegistry *registry; + + GtkWidget *tree_view; /* not referenced */ + GtkWidget *add_button; /* not referenced */ + GtkWidget *edit_button; /* not referenced */ + GtkWidget *delete_button; /* not referenced */ + GtkWidget *default_button; /* not referenced */ +}; + +enum { + PROP_0, + PROP_REGISTRY +}; + +enum { + ADD_ACCOUNT, + EDIT_ACCOUNT, + DELETE_ACCOUNT, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE ( + EMailAccountManager, + e_mail_account_manager, + GTK_TYPE_TABLE) + +static gboolean +mail_account_manager_key_press_event_cb (EMailAccountManager *manager, + GdkEventKey *event) +{ + if (event->keyval == GDK_KEY_Delete) { + e_mail_account_manager_delete_account (manager); + return TRUE; + } + + return FALSE; +} + +static void +mail_account_manager_selection_changed_cb (EMailAccountManager *manager, + GtkTreeSelection *selection) +{ + EMailAccountTreeView *tree_view; + ESourceRegistry *registry; + ESource *default_source; + ESource *source; + GtkWidget *add_button; + GtkWidget *edit_button; + GtkWidget *delete_button; + GtkWidget *default_button; + gboolean sensitive; + + add_button = manager->priv->add_button; + edit_button = manager->priv->edit_button; + delete_button = manager->priv->delete_button; + default_button = manager->priv->default_button; + + registry = e_mail_account_manager_get_registry (manager); + tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view); + + source = e_mail_account_tree_view_get_selected_source (tree_view); + default_source = e_source_registry_get_default_mail_account (registry); + + if (source == NULL) + gtk_widget_grab_focus (add_button); + + sensitive = (source != NULL); + gtk_widget_set_sensitive (edit_button, sensitive); + + sensitive = (source != NULL); + gtk_widget_set_sensitive (delete_button, sensitive); + + sensitive = (source != NULL && source != default_source); + gtk_widget_set_sensitive (default_button, sensitive); +} + +static void +mail_account_manager_set_registry (EMailAccountManager *manager, + ESourceRegistry *registry) +{ + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_return_if_fail (manager->priv->registry == NULL); + + manager->priv->registry = g_object_ref (registry); +} + +static void +mail_account_manager_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REGISTRY: + mail_account_manager_set_registry ( + E_MAIL_ACCOUNT_MANAGER (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_manager_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REGISTRY: + g_value_set_object ( + value, + e_mail_account_manager_get_registry ( + E_MAIL_ACCOUNT_MANAGER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_manager_dispose (GObject *object) +{ + EMailAccountManagerPrivate *priv; + + priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (object); + + if (priv->registry != NULL) { + g_object_unref (priv->registry); + priv->registry = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_account_manager_parent_class)->dispose (object); +} + +static void +mail_account_manager_constructed (GObject *object) +{ + EMailAccountManager *manager; + ESourceRegistry *registry; + GtkTreeSelection *selection; + GtkWidget *container; + GtkWidget *widget; + + manager = E_MAIL_ACCOUNT_MANAGER (object); + registry = e_mail_account_manager_get_registry (manager); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_account_manager_parent_class)-> + constructed (object); + + gtk_table_resize (GTK_TABLE (manager), 1, 2); + gtk_table_set_col_spacings (GTK_TABLE (manager), 6); + gtk_table_set_row_spacings (GTK_TABLE (manager), 12); + + container = GTK_WIDGET (manager); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_table_attach ( + GTK_TABLE (container), widget, 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = e_mail_account_tree_view_new (registry); + gtk_container_add (GTK_CONTAINER (container), widget); + manager->priv->tree_view = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (mail_account_manager_key_press_event_cb), + manager); + + g_signal_connect_swapped ( + widget, "row-activated", + G_CALLBACK (e_mail_account_manager_edit_account), + manager); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (mail_account_manager_selection_changed_cb), + manager); + + container = GTK_WIDGET (manager); + + widget = gtk_vbutton_box_new (); + gtk_button_box_set_layout ( + GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START); + gtk_box_set_spacing (GTK_BOX (widget), 6); + gtk_table_attach ( + GTK_TABLE (container), widget, + 1, 2, 0, 2, 0, GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_button_new_from_stock (GTK_STOCK_ADD); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->add_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_mail_account_manager_add_account), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_EDIT); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->edit_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_mail_account_manager_edit_account), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_DELETE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->delete_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_mail_account_manager_delete_account), manager); + + widget = gtk_button_new_with_mnemonic (_("De_fault")); + gtk_button_set_image ( + GTK_BUTTON (widget), + gtk_image_new_from_icon_name ( + "emblem-default", GTK_ICON_SIZE_BUTTON)); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->default_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_mail_account_tree_view_enable_selected), + manager->priv->tree_view); +} + +static void +e_mail_account_manager_class_init (EMailAccountManagerClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailAccountManagerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_account_manager_set_property; + object_class->get_property = mail_account_manager_get_property; + object_class->dispose = mail_account_manager_dispose; + object_class->constructed = mail_account_manager_constructed; + + /* XXX If we moved the account editor to /widgets/misc we + * could handle adding and editing accounts directly. */ + + g_object_class_install_property ( + object_class, + PROP_REGISTRY, + g_param_spec_object ( + "registry", + "Registry", + NULL, + E_TYPE_SOURCE_REGISTRY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[ADD_ACCOUNT] = g_signal_new ( + "add-account", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountManagerClass, add_account), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[EDIT_ACCOUNT] = g_signal_new ( + "edit-account", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountManagerClass, edit_account), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[DELETE_ACCOUNT] = g_signal_new ( + "delete-account", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountManagerClass, delete_account), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +e_mail_account_manager_init (EMailAccountManager *manager) +{ + manager->priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (manager); +} + +GtkWidget * +e_mail_account_manager_new (ESourceRegistry *registry) +{ + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + return g_object_new ( + E_TYPE_MAIL_ACCOUNT_MANAGER, + "registry", registry, NULL); +} + +void +e_mail_account_manager_add_account (EMailAccountManager *manager) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager)); + + g_signal_emit (manager, signals[ADD_ACCOUNT], 0); +} + +void +e_mail_account_manager_edit_account (EMailAccountManager *manager) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager)); + + g_signal_emit (manager, signals[EDIT_ACCOUNT], 0); +} + +void +e_mail_account_manager_delete_account (EMailAccountManager *manager) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager)); + + g_signal_emit (manager, signals[DELETE_ACCOUNT], 0); +} + +ESourceRegistry * +e_mail_account_manager_get_registry (EMailAccountManager *manager) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager), NULL); + + return manager->priv->registry; +} diff --git a/widgets/misc/e-mail-account-manager.h b/widgets/misc/e-mail-account-manager.h new file mode 100644 index 0000000000..4afbe7052d --- /dev/null +++ b/widgets/misc/e-mail-account-manager.h @@ -0,0 +1,77 @@ +/* + * e-mail-account-manager.h + * + * 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/> + * + */ + +#ifndef E_MAIL_ACCOUNT_MANAGER_H +#define E_MAIL_ACCOUNT_MANAGER_H + +#include <gtk/gtk.h> +#include <libedataserver/e-source-registry.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_ACCOUNT_MANAGER \ + (e_mail_account_manager_get_type ()) +#define E_MAIL_ACCOUNT_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManager)) +#define E_MAIL_ACCOUNT_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass)) +#define E_IS_MAIL_ACCOUNT_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER)) +#define E_IS_MAIL_ACCOUNT_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_INSTANCE_CLASS \ + ((cls), E_TYPE_MAIL_ACCOUNT_MANAGER)) +#define E_MAIL_ACCOUNT_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass)) + +G_BEGIN_DECLS + +typedef struct _EMailAccountManager EMailAccountManager; +typedef struct _EMailAccountManagerClass EMailAccountManagerClass; +typedef struct _EMailAccountManagerPrivate EMailAccountManagerPrivate; + +struct _EMailAccountManager { + GtkTable parent; + EMailAccountManagerPrivate *priv; +}; + +struct _EMailAccountManagerClass { + GtkTableClass parent_class; + + void (*add_account) (EMailAccountManager *manager); + void (*edit_account) (EMailAccountManager *manager); + void (*delete_account) (EMailAccountManager *manager); +}; + +GType e_mail_account_manager_get_type (void) G_GNUC_CONST; +GtkWidget * e_mail_account_manager_new (ESourceRegistry *registry); +void e_mail_account_manager_add_account + (EMailAccountManager *manager); +void e_mail_account_manager_edit_account + (EMailAccountManager *manager); +void e_mail_account_manager_delete_account + (EMailAccountManager *manager); +ESourceRegistry * + e_mail_account_manager_get_registry + (EMailAccountManager *manager); + +G_END_DECLS + +#endif /* E_MAIL_ACCOUNT_MANAGER_H */ diff --git a/widgets/misc/e-mail-account-tree-view.c b/widgets/misc/e-mail-account-tree-view.c new file mode 100644 index 0000000000..45d6a0d72e --- /dev/null +++ b/widgets/misc/e-mail-account-tree-view.c @@ -0,0 +1,575 @@ +/* + * e-mail-account-tree-view.c + * + * 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/> + * + */ + +#include "e-mail-account-tree-view.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libedataserver/e-source-mail-account.h> + +#define E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewPrivate)) + +#define SOURCE_IS_MAIL_ACCOUNT(source) \ + (e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_ACCOUNT)) + +struct _EMailAccountTreeViewPrivate { + ESourceRegistry *registry; + guint refresh_idle_id; +}; + +enum { + PROP_0, + PROP_REGISTRY +}; + +enum { + ENABLE_SELECTED, + DISABLE_SELECTED, + LAST_SIGNAL +}; + +enum { + COLUMN_DISPLAY_NAME, + COLUMN_BACKEND_NAME, + COLUMN_DEFAULT, + COLUMN_ENABLED, + COLUMN_UID +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE ( + EMailAccountTreeView, + e_mail_account_tree_view, + GTK_TYPE_TREE_VIEW) + +static gboolean +mail_account_tree_view_refresh_idle_cb (EMailAccountTreeView *tree_view) +{ + /* The refresh function will clear the idle ID. */ + e_mail_account_tree_view_refresh (tree_view); + + return FALSE; +} + +static void +mail_account_tree_view_registry_changed (ESourceRegistry *registry, + ESource *source, + EMailAccountTreeView *tree_view) +{ + /* If the ESource in question has a "Mail Account" extension, + * schedule a refresh of the tree model. Otherwise ignore it. + * We use an idle callback to limit how frequently we refresh + * the tree model, in case the registry is emitting lots of + * signals at once. */ + + if (!SOURCE_IS_MAIL_ACCOUNT (source)) + return; + + if (tree_view->priv->refresh_idle_id > 0) + return; + + tree_view->priv->refresh_idle_id = gdk_threads_add_idle ( + (GSourceFunc) mail_account_tree_view_refresh_idle_cb, + tree_view); +} + +static void +mail_account_tree_view_enabled_toggled_cb (GtkCellRendererToggle *cell_renderer, + const gchar *path_string, + EMailAccountTreeView *tree_view) +{ + GtkTreeSelection *selection; + GtkTreePath *path; + + /* Chain the selection first so we enable or disable the + * correct account. */ + path = gtk_tree_path_new_from_string (path_string); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + gtk_tree_selection_select_path (selection, path); + gtk_tree_path_free (path); + + if (gtk_cell_renderer_toggle_get_active (cell_renderer)) + e_mail_account_tree_view_disable_selected (tree_view); + else + e_mail_account_tree_view_enable_selected (tree_view); +} + +static void +mail_account_tree_view_set_registry (EMailAccountTreeView *tree_view, + ESourceRegistry *registry) +{ + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_return_if_fail (tree_view->priv->registry == NULL); + + tree_view->priv->registry = g_object_ref (registry); + + g_signal_connect ( + registry, "source-added", + G_CALLBACK (mail_account_tree_view_registry_changed), + tree_view); + + g_signal_connect ( + registry, "source-changed", + G_CALLBACK (mail_account_tree_view_registry_changed), + tree_view); + + g_signal_connect ( + registry, "source-removed", + G_CALLBACK (mail_account_tree_view_registry_changed), + tree_view); +} + +static void +mail_account_tree_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REGISTRY: + mail_account_tree_view_set_registry ( + E_MAIL_ACCOUNT_TREE_VIEW (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_tree_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REGISTRY: + g_value_set_object ( + value, + e_mail_account_tree_view_get_registry ( + E_MAIL_ACCOUNT_TREE_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_tree_view_dispose (GObject *object) +{ + EMailAccountTreeViewPrivate *priv; + + priv = E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE (object); + + if (priv->registry != NULL) { + g_signal_handlers_disconnect_matched ( + priv->registry, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->registry); + priv->registry = NULL; + } + + if (priv->refresh_idle_id > 0) { + g_source_remove (priv->refresh_idle_id); + priv->refresh_idle_id = 0; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_account_tree_view_parent_class)-> + dispose (object); +} + +static void +mail_account_tree_view_constructed (GObject *object) +{ + GtkTreeView *tree_view; + GtkTreeViewColumn *column; + GtkCellRenderer *cell_renderer; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_account_tree_view_parent_class)-> + constructed (object); + + tree_view = GTK_TREE_VIEW (object); + gtk_tree_view_set_headers_visible (tree_view, TRUE); + + /* Column: Enabled */ + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, FALSE); + gtk_tree_view_column_set_title (column, _("Enabled")); + + cell_renderer = gtk_cell_renderer_toggle_new (); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + + g_signal_connect ( + cell_renderer, "toggled", + G_CALLBACK (mail_account_tree_view_enabled_toggled_cb), + tree_view); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "active", COLUMN_ENABLED); + + gtk_tree_view_append_column (tree_view, column); + + /* Column: Account Name */ + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_column_set_title (column, _("Account Name")); + + cell_renderer = gtk_cell_renderer_text_new (); + g_object_set (cell_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "text", COLUMN_DISPLAY_NAME); + + cell_renderer = gtk_cell_renderer_text_new (); + g_object_set (cell_renderer, "text", _("Default"), NULL); + gtk_tree_view_column_pack_end (column, cell_renderer, FALSE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "visible", COLUMN_DISPLAY_NAME); + + cell_renderer = gtk_cell_renderer_pixbuf_new (); + g_object_set ( + cell_renderer, "icon-name", "emblem-default", + "stock-size", GTK_ICON_SIZE_MENU, NULL); + gtk_tree_view_column_pack_end (column, cell_renderer, FALSE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "visible", COLUMN_DISPLAY_NAME); + + gtk_tree_view_append_column (tree_view, column); + + /* Column: Type */ + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, FALSE); + gtk_tree_view_column_set_title (column, _("Type")); + + cell_renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "text", COLUMN_BACKEND_NAME); + + gtk_tree_view_append_column (tree_view, column); + + e_mail_account_tree_view_refresh (E_MAIL_ACCOUNT_TREE_VIEW (object)); +} + +static void +mail_account_tree_view_enable_selected (EMailAccountTreeView *tree_view) +{ + ESource *source; + ESourceMailAccount *mail_account; + const gchar *extension_name; + GError *error = NULL; + + source = e_mail_account_tree_view_get_selected_source (tree_view); + + if (source == NULL) + return; + + /* The source should already be a mail account. */ + g_return_if_fail (SOURCE_IS_MAIL_ACCOUNT (source)); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + mail_account = e_source_get_extension (source, extension_name); + + /* Avoid unnecessary signal emissions and disk writes. */ + if (e_source_mail_account_get_enabled (mail_account)) + return; + + e_source_mail_account_set_enabled (mail_account, TRUE); + + if (!e_source_sync (source, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +} + +static void +mail_account_tree_view_disable_selected (EMailAccountTreeView *tree_view) +{ + ESource *source; + ESourceMailAccount *mail_account; + const gchar *extension_name; + GError *error = NULL; + + source = e_mail_account_tree_view_get_selected_source (tree_view); + + if (source == NULL) + return; + + /* The source should already be a mail account. */ + g_return_if_fail (SOURCE_IS_MAIL_ACCOUNT (source)); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + mail_account = e_source_get_extension (source, extension_name); + + /* Avoid unnecessary signal emissions and disk writes. */ + if (!e_source_mail_account_get_enabled (mail_account)) + return; + + e_source_mail_account_set_enabled (mail_account, FALSE); + + if (!e_source_sync (source, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +} + +static void +e_mail_account_tree_view_class_init (EMailAccountTreeViewClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailAccountTreeViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_account_tree_view_set_property; + object_class->get_property = mail_account_tree_view_get_property; + object_class->dispose = mail_account_tree_view_dispose; + object_class->constructed = mail_account_tree_view_constructed; + + class->enable_selected = mail_account_tree_view_enable_selected; + class->disable_selected = mail_account_tree_view_disable_selected; + + g_object_class_install_property ( + object_class, + PROP_REGISTRY, + g_param_spec_object ( + "registry", + "Registry", + NULL, + E_TYPE_SOURCE_REGISTRY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + signals[ENABLE_SELECTED] = g_signal_new ( + "enable-selected", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountTreeViewClass, enable_selected), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[DISABLE_SELECTED] = g_signal_new ( + "disable-selected", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountTreeViewClass, disable_selected), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +e_mail_account_tree_view_init (EMailAccountTreeView *tree_view) +{ + tree_view->priv = E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE (tree_view); +} + +GtkWidget * +e_mail_account_tree_view_new (ESourceRegistry *registry) +{ + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + return g_object_new ( + E_TYPE_MAIL_ACCOUNT_TREE_VIEW, + "registry", registry, NULL); +} + +void +e_mail_account_tree_view_refresh (EMailAccountTreeView *tree_view) +{ + ESourceRegistry *registry; + GtkTreeModel *tree_model; + ESource *default_source; + ESource *source; + GList *list, *link; + const gchar *extension_name; + gchar *saved_uid = NULL; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view)); + + if (tree_view->priv->refresh_idle_id > 0) { + g_source_remove (tree_view->priv->refresh_idle_id); + tree_view->priv->refresh_idle_id = 0; + } + + registry = e_mail_account_tree_view_get_registry (tree_view); + tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + + source = e_mail_account_tree_view_get_selected_source (tree_view); + if (source != NULL) + saved_uid = g_strdup (e_source_get_uid (source)); + + default_source = e_source_registry_get_default_mail_account (registry); + + gtk_list_store_clear (GTK_LIST_STORE (tree_model)); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + list = e_source_registry_list_sources (registry, extension_name); + + for (link = list; link != NULL; link = g_list_next (link)) { + ESourceMailAccount *mail_account; + GtkTreeIter iter; + const gchar *backend_name; + const gchar *display_name; + const gchar *uid; + gboolean is_default; + gboolean is_enabled; + + source = E_SOURCE (link->data); + mail_account = e_source_get_extension (source, extension_name); + + display_name = e_source_get_display_name (source); + backend_name = e_source_get_backend_name (source); + is_default = e_source_equal (source, default_source); + is_enabled = e_source_mail_account_get_enabled (mail_account); + uid = e_source_get_uid (source); + + gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter); + + gtk_list_store_set ( + GTK_LIST_STORE (tree_model), &iter, + COLUMN_DISPLAY_NAME, display_name, + COLUMN_BACKEND_NAME, backend_name, + COLUMN_DEFAULT, is_default, + COLUMN_ENABLED, is_enabled, + COLUMN_UID, uid, -1); + } + + g_list_free (list); + + /* Try and restore the previous selected source, + * or else just pick the default mail account. */ + + source = NULL; + + if (saved_uid != NULL) { + source = e_source_registry_lookup_by_uid (registry, saved_uid); + g_free (saved_uid); + } + + if (source == NULL) + source = default_source; + + if (source != NULL) + e_mail_account_tree_view_set_selected_source ( + tree_view, source); +} + +void +e_mail_account_tree_view_enable_selected (EMailAccountTreeView *tree_view) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view)); + + g_signal_emit (tree_view, signals[ENABLE_SELECTED], 0); +} + +void +e_mail_account_tree_view_disable_selected (EMailAccountTreeView *tree_view) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view)); + + g_signal_emit (tree_view, signals[DISABLE_SELECTED], 0); +} + +ESourceRegistry * +e_mail_account_tree_view_get_registry (EMailAccountTreeView *tree_view) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view), NULL); + + return tree_view->priv->registry; +} + +ESource * +e_mail_account_tree_view_get_selected_source (EMailAccountTreeView *tree_view) +{ + ESourceRegistry *registry; + GtkTreeSelection *selection; + GtkTreeModel *tree_model; + GtkTreeIter iter; + ESource *source; + gchar *uid; + + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view), NULL); + + registry = e_mail_account_tree_view_get_registry (tree_view); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + + if (!gtk_tree_selection_get_selected (selection, &tree_model, &iter)) + return NULL; + + gtk_tree_model_get (tree_model, &iter, COLUMN_UID, &uid, -1); + source = e_source_registry_lookup_by_uid (registry, uid); + g_free (uid); + + return source; +} + +void +e_mail_account_tree_view_set_selected_source (EMailAccountTreeView *tree_view, + ESource *source) +{ + ESourceRegistry *registry; + GtkTreeSelection *selection; + GtkTreeModel *tree_model; + GtkTreeIter iter; + gboolean valid; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view)); + g_return_if_fail (E_IS_SOURCE (source)); + + /* It is a programming error to pass an ESource that has no + * "Mail Account" extension. */ + g_return_if_fail (SOURCE_IS_MAIL_ACCOUNT (source)); + + registry = e_mail_account_tree_view_get_registry (tree_view); + tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + ESource *candidate; + gchar *uid; + + gtk_tree_model_get (tree_model, &iter, COLUMN_UID, &uid, -1); + candidate = e_source_registry_lookup_by_uid (registry, uid); + g_free (uid); + + if (candidate != NULL && e_source_equal (source, candidate)) { + gtk_tree_selection_select_iter (selection, &iter); + break; + } + + valid = gtk_tree_model_iter_next (tree_model, &iter); + } +} diff --git a/widgets/misc/e-mail-account-tree-view.h b/widgets/misc/e-mail-account-tree-view.h new file mode 100644 index 0000000000..4bf9099191 --- /dev/null +++ b/widgets/misc/e-mail-account-tree-view.h @@ -0,0 +1,83 @@ +/* + * e-mail-account-tree-view.h + * + * 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/> + * + */ + +#ifndef E_MAIL_ACCOUNT_TREE_VIEW_H +#define E_MAIL_ACCOUNT_TREE_VIEW_H + +#include <gtk/gtk.h> +#include <libedataserver/e-source-registry.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_ACCOUNT_TREE_VIEW \ + (e_mail_account_tree_view_get_type ()) +#define E_MAIL_ACCOUNT_TREE_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeView)) +#define E_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass)) +#define E_IS_MAIL_ACCOUNT_TREE_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW)) +#define E_IS_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW)) +#define E_MAIL_ACCOUNT_TREE_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass)) + +G_BEGIN_DECLS + +typedef struct _EMailAccountTreeView EMailAccountTreeView; +typedef struct _EMailAccountTreeViewClass EMailAccountTreeViewClass; +typedef struct _EMailAccountTreeViewPrivate EMailAccountTreeViewPrivate; + +struct _EMailAccountTreeView { + GtkTreeView parent; + EMailAccountTreeViewPrivate *priv; +}; + +struct _EMailAccountTreeViewClass { + GtkTreeViewClass parent_class; + + void (*enable_selected) (EMailAccountTreeView *tree_view); + void (*disable_selected) (EMailAccountTreeView *tree_view); +}; + +GType e_mail_account_tree_view_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_account_tree_view_new + (ESourceRegistry *registry); +void e_mail_account_tree_view_refresh + (EMailAccountTreeView *tree_view); +void e_mail_account_tree_view_enable_selected + (EMailAccountTreeView *tree_view); +void e_mail_account_tree_view_disable_selected + (EMailAccountTreeView *tree_view); +ESourceRegistry * + e_mail_account_tree_view_get_registry + (EMailAccountTreeView *tree_view); +ESource * e_mail_account_tree_view_get_selected_source + (EMailAccountTreeView *tree_view); +void e_mail_account_tree_view_set_selected_source + (EMailAccountTreeView *tree_view, + ESource *source); + +G_END_DECLS + +#endif /* E_MAIL_ACCOUNT_TREE_VIEW_H */ diff --git a/widgets/misc/e-mail-identity-combo-box.c b/widgets/misc/e-mail-identity-combo-box.c new file mode 100644 index 0000000000..4b830153a2 --- /dev/null +++ b/widgets/misc/e-mail-identity-combo-box.c @@ -0,0 +1,374 @@ +/* + * e-mail-identity-combo-box.c + * + * 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/> + * + */ + +#include "e-mail-identity-combo-box.h" + +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-identity.h> + +#define E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBoxPrivate)) + +#define SOURCE_IS_MAIL_IDENTITY(source) \ + (e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_IDENTITY)) + +struct _EMailIdentityComboBoxPrivate { + ESourceRegistry *registry; + guint refresh_idle_id; +}; + +enum { + PROP_0, + PROP_REGISTRY +}; + +enum { + COLUMN_DISPLAY_NAME, + COLUMN_UID +}; + +G_DEFINE_TYPE ( + EMailIdentityComboBox, + e_mail_identity_combo_box, + GTK_TYPE_COMBO_BOX) + +static gboolean +mail_identity_combo_box_refresh_idle_cb (EMailIdentityComboBox *combo_box) +{ + /* The refresh function will clear the idle ID. */ + e_mail_identity_combo_box_refresh (combo_box); + + return FALSE; +} + +static void +mail_identity_combo_box_registry_changed (ESourceRegistry *registry, + ESource *source, + EMailIdentityComboBox *combo_box) +{ + /* If the ESource in question has a "Mail Identity" extension, + * schedule a refresh of the tree model. Otherwise ignore it. + * We use an idle callback to limit how frequently we refresh + * the tree model, in case the registry is emitting lots of + * signals at once. */ + + if (!SOURCE_IS_MAIL_IDENTITY (source)) + return; + + if (combo_box->priv->refresh_idle_id > 0) + return; + + combo_box->priv->refresh_idle_id = gdk_threads_add_idle ( + (GSourceFunc) mail_identity_combo_box_refresh_idle_cb, + combo_box); +} + +static ESource * +mail_identity_combo_box_get_default (EMailIdentityComboBox *combo_box) +{ + ESource *source; + ESourceRegistry *registry; + ESourceMailAccount *mail_account; + const gchar *extension_name; + const gchar *uid; + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + registry = e_mail_identity_combo_box_get_registry (combo_box); + source = e_source_registry_get_default_mail_account (registry); + + if (source == NULL) + return NULL; + + if (!e_source_has_extension (source, extension_name)) + return NULL; + + mail_account = e_source_get_extension (source, extension_name); + uid = e_source_mail_account_get_identity (mail_account); + + if (uid == NULL) + return NULL; + + return e_source_registry_lookup_by_uid (registry, uid); +} + +static void +mail_identity_combo_box_set_registry (EMailIdentityComboBox *combo_box, + ESourceRegistry *registry) +{ + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_return_if_fail (combo_box->priv->registry == NULL); + + combo_box->priv->registry = g_object_ref (registry); + + g_signal_connect ( + registry, "source-added", + G_CALLBACK (mail_identity_combo_box_registry_changed), + combo_box); + + g_signal_connect ( + registry, "source-changed", + G_CALLBACK (mail_identity_combo_box_registry_changed), + combo_box); + + g_signal_connect ( + registry, "source-removed", + G_CALLBACK (mail_identity_combo_box_registry_changed), + combo_box); +} + +static void +mail_identity_combo_box_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REGISTRY: + mail_identity_combo_box_set_registry ( + E_MAIL_IDENTITY_COMBO_BOX (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_identity_combo_box_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REGISTRY: + g_value_set_object ( + value, + e_mail_identity_combo_box_get_registry ( + E_MAIL_IDENTITY_COMBO_BOX (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_identity_combo_box_dispose (GObject *object) +{ + EMailIdentityComboBoxPrivate *priv; + + priv = E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE (object); + + if (priv->registry != NULL) { + g_signal_handlers_disconnect_matched ( + priv->registry, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->registry); + priv->registry = NULL; + } + + if (priv->refresh_idle_id > 0) { + g_source_remove (priv->refresh_idle_id); + priv->refresh_idle_id = 0; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_identity_combo_box_parent_class)-> + dispose (object); +} + +static void +mail_identity_combo_box_constructed (GObject *object) +{ + GtkListStore *list_store; + GtkComboBox *combo_box; + GtkCellLayout *cell_layout; + GtkCellRenderer *cell_renderer; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_identity_combo_box_parent_class)-> + constructed (object); + + combo_box = GTK_COMBO_BOX (object); + cell_layout = GTK_CELL_LAYOUT (object); + + list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (list_store)); + gtk_combo_box_set_id_column (combo_box, COLUMN_UID); + g_object_unref (list_store); + + cell_renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (cell_layout, cell_renderer, TRUE); + gtk_cell_layout_add_attribute ( + cell_layout, cell_renderer, "text", COLUMN_DISPLAY_NAME); + + e_mail_identity_combo_box_refresh (E_MAIL_IDENTITY_COMBO_BOX (object)); +} + +static void +e_mail_identity_combo_box_class_init (EMailIdentityComboBoxClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailIdentityComboBoxPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_identity_combo_box_set_property; + object_class->get_property = mail_identity_combo_box_get_property; + object_class->dispose = mail_identity_combo_box_dispose; + object_class->constructed = mail_identity_combo_box_constructed; + + g_object_class_install_property ( + object_class, + PROP_REGISTRY, + g_param_spec_object ( + "registry", + "Registry", + NULL, + E_TYPE_SOURCE_REGISTRY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_identity_combo_box_init (EMailIdentityComboBox *combo_box) +{ + combo_box->priv = E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE (combo_box); +} + +GtkWidget * +e_mail_identity_combo_box_new (ESourceRegistry *registry) +{ + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + return g_object_new ( + E_TYPE_MAIL_IDENTITY_COMBO_BOX, + "registry", registry, NULL); +} + +void +e_mail_identity_combo_box_refresh (EMailIdentityComboBox *combo_box) +{ + ESourceRegistry *registry; + GtkTreeModel *tree_model; + ESource *source; + GList *list, *link; + const gchar *extension_name; + gchar *saved_uid = NULL; + + g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box)); + + if (combo_box->priv->refresh_idle_id > 0) { + g_source_remove (combo_box->priv->refresh_idle_id); + combo_box->priv->refresh_idle_id = 0; + } + + registry = e_mail_identity_combo_box_get_registry (combo_box); + tree_model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); + + source = e_mail_identity_combo_box_get_active_source (combo_box); + if (source != NULL) + saved_uid = g_strdup (e_source_get_uid (source)); + + gtk_list_store_clear (GTK_LIST_STORE (tree_model)); + + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + list = e_source_registry_list_sources (registry, extension_name); + + for (link = list; link != NULL; link = g_list_next (link)) { + GtkTreeIter iter; + const gchar *display_name; + const gchar *uid; + + source = E_SOURCE (link->data); + display_name = e_source_get_display_name (source); + uid = e_source_get_uid (source); + + gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter); + + gtk_list_store_set ( + GTK_LIST_STORE (tree_model), &iter, + COLUMN_DISPLAY_NAME, display_name, + COLUMN_UID, uid, -1); + } + + g_list_free (list); + + /* Try and restore the previous selected source, or else pick + * the default identity of the default mail account. If even + * that fails, just pick the first item. */ + + source = NULL; + + if (saved_uid != NULL) { + source = e_source_registry_lookup_by_uid (registry, saved_uid); + g_free (saved_uid); + } + + if (source == NULL) + source = mail_identity_combo_box_get_default (combo_box); + + if (source != NULL) + e_mail_identity_combo_box_set_active_source (combo_box, source); + else + gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0); +} + +ESourceRegistry * +e_mail_identity_combo_box_get_registry (EMailIdentityComboBox *combo_box) +{ + g_return_val_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box), NULL); + + return combo_box->priv->registry; +} + +ESource * +e_mail_identity_combo_box_get_active_source (EMailIdentityComboBox *combo_box) +{ + ESourceRegistry *registry; + ESource *source = NULL; + const gchar *uid; + + g_return_val_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box), NULL); + + registry = e_mail_identity_combo_box_get_registry (combo_box); + uid = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box)); + + if (uid != NULL) + source = e_source_registry_lookup_by_uid (registry, uid); + + return source; +} + +void +e_mail_identity_combo_box_set_active_source (EMailIdentityComboBox *combo_box, + ESource *active_source) +{ + const gchar *uid; + + g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box)); + g_return_if_fail (E_IS_SOURCE (active_source)); + + /* It is a programming error to pass an ESource that has no + * "Mail Identity" extension. */ + g_return_if_fail (SOURCE_IS_MAIL_IDENTITY (active_source)); + + uid = e_source_get_uid (active_source); + gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), uid); +} diff --git a/widgets/misc/e-mail-identity-combo-box.h b/widgets/misc/e-mail-identity-combo-box.h new file mode 100644 index 0000000000..b40957df7a --- /dev/null +++ b/widgets/misc/e-mail-identity-combo-box.h @@ -0,0 +1,76 @@ +/* + * e-mail-identity-combo-box.h + * + * 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/> + * + */ + +#ifndef E_MAIL_IDENTITY_COMBO_BOX_H +#define E_MAIL_IDENTITY_COMBO_BOX_H + +#include <gtk/gtk.h> +#include <libedataserver/e-source-registry.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_IDENTITY_COMBO_BOX \ + (e_mail_identity_combo_box_get_type ()) +#define E_MAIL_IDENTITY_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBox)) +#define E_MAIL_IDENTITY_COMBO_BOX_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBoxClass)) +#define E_IS_MAIL_IDENTITY_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX)) +#define E_IS_MAIL_IDENTITY_COMBO_BOX_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_IDENTITY_COMBO_BOX)) +#define E_MAIL_IDENTITY_COMBO_BOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBoxClass)) + +G_BEGIN_DECLS + +typedef struct _EMailIdentityComboBox EMailIdentityComboBox; +typedef struct _EMailIdentityComboBoxClass EMailIdentityComboBoxClass; +typedef struct _EMailIdentityComboBoxPrivate EMailIdentityComboBoxPrivate; + +struct _EMailIdentityComboBox { + GtkComboBox parent; + EMailIdentityComboBoxPrivate *priv; +}; + +struct _EMailIdentityComboBoxClass { + GtkComboBoxClass parent_class; +}; + +GType e_mail_identity_combo_box_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_identity_combo_box_new + (ESourceRegistry *registry); +void e_mail_identity_combo_box_refresh + (EMailIdentityComboBox *combo_box); +ESourceRegistry * + e_mail_identity_combo_box_get_registry + (EMailIdentityComboBox *combo_box); +ESource * e_mail_identity_combo_box_get_active_source + (EMailIdentityComboBox *combo_box); +void e_mail_identity_combo_box_set_active_source + (EMailIdentityComboBox *combo_box, + ESource *active_source); + +G_END_DECLS + +#endif /* E_MAIL_IDENTITY_COMBO_BOX_H */ diff --git a/widgets/misc/test-mail-accounts.c b/widgets/misc/test-mail-accounts.c new file mode 100644 index 0000000000..92069b4bb2 --- /dev/null +++ b/widgets/misc/test-mail-accounts.c @@ -0,0 +1,61 @@ +/* + * test-mail-accounts.c + * + * 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/> + * + */ + +#include <misc/e-mail-account-manager.h> +#include <misc/e-mail-identity-combo-box.h> + +gint +main (gint argc, gchar **argv) +{ + ESourceRegistry *registry; + GtkWidget *container; + GtkWidget *widget; + GtkWidget *window; + + gtk_init (&argc, &argv); + + registry = e_source_registry_get_default (); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Mail Sources"); + gtk_widget_set_default_size (GTK_WINDOW (window), 400, 400); + gtk_container_set_border_width (GTK_CONTAINER (window), 12); + gtk_widget_show (window); + + g_signal_connect ( + window, "delete-event", + G_CALLBACK (gtk_main_quit), NULL); + + widget = gtk_vbox_new (FALSE, 12); + gtk_container_add (GTK_CONTAINER (window), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_mail_identity_combo_box_new (registry); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = e_mail_account_manager_new (registry); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + gtk_main (); + + return 0; +} |