diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2011-04-13 22:30:40 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2012-06-03 11:00:40 +0800 |
commit | 3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81 (patch) | |
tree | ff59febf4ac0c6316ef344ea25cee002088bd314 /mail | |
parent | f78795f4dff8b225d78385c5e23e1cd44ee946ad (diff) | |
download | gsoc2013-evolution-3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81.tar gsoc2013-evolution-3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81.tar.gz gsoc2013-evolution-3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81.tar.bz2 gsoc2013-evolution-3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81.tar.lz gsoc2013-evolution-3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81.tar.xz gsoc2013-evolution-3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81.tar.zst gsoc2013-evolution-3449e5fcc7f9c797fcde7f2a444b1eb7a934cd81.zip |
Adapt mail to the new ESource API.
Diffstat (limited to 'mail')
67 files changed, 13915 insertions, 10595 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am index 7358f359a5..d1c4fddce9 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -45,8 +45,28 @@ mailinclude_HEADERS = \ e-mail-account-store.h \ e-mail-account-tree-view.h \ e-mail-attachment-bar.h \ + e-mail-autoconfig.h \ e-mail-backend.h \ e-mail-browser.h \ + e-mail-config-assistant.h \ + e-mail-config-auth-check.h \ + e-mail-config-confirm-page.h \ + e-mail-config-defaults-page.h \ + e-mail-config-identity-page.h \ + e-mail-config-lookup-page.h \ + e-mail-config-notebook.h \ + e-mail-config-page.h \ + e-mail-config-provider-page.h \ + e-mail-config-receiving-page.h \ + e-mail-config-security-page.h \ + e-mail-config-sending-page.h \ + e-mail-config-service-backend.h \ + e-mail-config-service-notebook.h \ + e-mail-config-service-page.h \ + e-mail-config-sidebar.h \ + e-mail-config-summary-page.h \ + e-mail-config-welcome-page.h \ + e-mail-config-window.h \ e-mail-display.h \ e-mail-folder-pane.h \ e-mail-junk-options.h \ @@ -67,7 +87,6 @@ mailinclude_HEADERS = \ e-mail-tag-editor.h \ e-mail-ui-session.h \ e-mail-view.h \ - em-account-editor.h \ em-composer-utils.h \ em-config.h \ em-event.h \ @@ -111,8 +130,28 @@ libevolution_mail_la_SOURCES = \ e-mail-account-store.c \ e-mail-account-tree-view.c \ e-mail-attachment-bar.c \ + e-mail-autoconfig.c \ e-mail-backend.c \ e-mail-browser.c \ + e-mail-config-assistant.c \ + e-mail-config-auth-check.c \ + e-mail-config-confirm-page.c \ + e-mail-config-defaults-page.c \ + e-mail-config-identity-page.c \ + e-mail-config-lookup-page.c \ + e-mail-config-notebook.c \ + e-mail-config-page.c \ + e-mail-config-provider-page.c \ + e-mail-config-receiving-page.c \ + e-mail-config-security-page.c \ + e-mail-config-sending-page.c \ + e-mail-config-service-backend.c \ + e-mail-config-service-notebook.c \ + e-mail-config-service-page.c \ + e-mail-config-sidebar.c \ + e-mail-config-summary-page.c \ + e-mail-config-welcome-page.c \ + e-mail-config-window.c \ e-mail-display.c \ e-mail-folder-pane.c \ e-mail-junk-options.c \ @@ -133,7 +172,6 @@ libevolution_mail_la_SOURCES = \ e-mail-tag-editor.c \ e-mail-ui-session.c \ e-mail-view.c \ - em-account-editor.c \ em-composer-utils.c \ em-config.c \ em-event.c \ @@ -202,12 +240,29 @@ libevolution_mail_la_LIBADD = \ $(E_WIDGETS_LIBS) \ $(SMIME_LIBS) \ $(LIBSOUP_LIBS) \ - $(GNOME_PLATFORM_LIBS) + -lresolv libevolution_mail_la_LDFLAGS = -avoid-version $(NO_UNDEFINED) libevolution_mail_la_DEPENDENCIES = em-filter-i18n.h +noinst_PROGRAMS = test-mail-autoconfig + +test_mail_autoconfig_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(EVOLUTION_DATA_SERVER_CFLAGS) \ + $(GNOME_PLATFORM_CFLAGS) + +test_mail_autoconfig_SOURCES = \ + e-mail-autoconfig.c \ + e-mail-autoconfig.h \ + test-mail-autoconfig.c + +test_mail_autoconfig_LDADD = \ + $(EVOLUTION_DATA_SERVER_LIBS) \ + $(GNOME_PLATFORM_LIBS) \ + -lresolv + # Misc data to install filterdir = $(privdatadir) filter_DATA = filtertypes.xml vfoldertypes.xml searchtypes.xml diff --git a/mail/e-mail-account-manager.c b/mail/e-mail-account-manager.c index 86a0bf5e4b..5cf6012351 100644 --- a/mail/e-mail-account-manager.c +++ b/mail/e-mail-account-manager.c @@ -22,6 +22,8 @@ #include <glib/gi18n-lib.h> #include <gdk/gdkkeysyms.h> +#include <libedataserver/e-source-collection.h> + #include <libemail-engine/e-mail-session.h> #include <mail/e-mail-account-tree-view.h> @@ -70,18 +72,27 @@ static void mail_account_manager_edit_cb (EMailAccountManager *manager) { EMailAccountTreeView *tree_view; - EAccount *account; + EMailAccountStore *store; + ESourceRegistry *registry; + EMailSession *session; CamelService *service; + ESource *source; const gchar *uid; + store = e_mail_account_manager_get_store (manager); + session = e_mail_account_store_get_session (store); + registry = e_mail_session_get_registry (session); + tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view); service = e_mail_account_tree_view_get_selected_service (tree_view); uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); - g_return_if_fail (account != NULL); + source = e_source_registry_ref_source (registry, uid); + g_return_if_fail (source != NULL); - e_mail_account_manager_edit_account (manager, account); + e_mail_account_manager_edit_account (manager, source); + + g_object_unref (source); } static void @@ -209,6 +220,7 @@ mail_account_manager_selection_changed_cb (EMailAccountManager *manager, gboolean builtin; gboolean sensitive; gboolean not_default; + gboolean removable; add_button = manager->priv->add_button; edit_button = manager->priv->edit_button; @@ -221,9 +233,11 @@ mail_account_manager_selection_changed_cb (EMailAccountManager *manager, E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service, E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, &builtin, -1); + removable = !builtin; } else { service = NULL; builtin = FALSE; + removable = FALSE; } store = e_mail_account_manager_get_store (manager); @@ -232,11 +246,40 @@ mail_account_manager_selection_changed_cb (EMailAccountManager *manager, if (service == NULL) gtk_widget_grab_focus (add_button); + else { + ESource *source; + EMailSession *session; + ESourceRegistry *registry; + const gchar *uid; + + session = e_mail_account_store_get_session (store); + registry = e_mail_session_get_registry (session); + + uid = camel_service_get_uid (service); + source = e_source_registry_ref_source (registry, uid); + + if (source != NULL) { + ESource *collection; + const gchar *extension_name; + + extension_name = E_SOURCE_EXTENSION_COLLECTION; + collection = e_source_registry_find_extension ( + registry, source, extension_name); + if (collection != NULL) { + g_object_unref (source); + source = collection; + } + + removable = e_source_get_removable (source); + + g_object_unref (source); + } + } sensitive = (service != NULL && !builtin); gtk_widget_set_sensitive (edit_button, sensitive); - sensitive = (service != NULL && !builtin); + sensitive = (service != NULL && removable); gtk_widget_set_sensitive (delete_button, sensitive); sensitive = (service != NULL && !builtin && not_default); @@ -519,7 +562,7 @@ e_mail_account_manager_class_init (EMailAccountManagerClass *class) NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - E_TYPE_ACCOUNT); + E_TYPE_SOURCE); } static void @@ -556,11 +599,11 @@ e_mail_account_manager_add_account (EMailAccountManager *manager) void e_mail_account_manager_edit_account (EMailAccountManager *manager, - EAccount *account) + ESource *source) { g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager)); - g_return_if_fail (E_IS_ACCOUNT (account)); + g_return_if_fail (E_IS_SOURCE (source)); - g_signal_emit (manager, signals[EDIT_ACCOUNT], 0, account); + g_signal_emit (manager, signals[EDIT_ACCOUNT], 0, source); } diff --git a/mail/e-mail-account-manager.h b/mail/e-mail-account-manager.h index 63e52b463c..a17ff2a317 100644 --- a/mail/e-mail-account-manager.h +++ b/mail/e-mail-account-manager.h @@ -20,8 +20,8 @@ #define E_MAIL_ACCOUNT_MANAGER_H #include <gtk/gtk.h> +#include <libedataserver/e-source.h> #include <mail/e-mail-account-store.h> -#include <libemail-utils/e-account-utils.h> /* Standard GObject macros */ #define E_TYPE_MAIL_ACCOUNT_MANAGER \ @@ -59,7 +59,7 @@ struct _EMailAccountManagerClass { /* Signals */ void (*add_account) (EMailAccountManager *manager); void (*edit_account) (EMailAccountManager *manager, - EAccount *account); + ESource *source); }; GType e_mail_account_manager_get_type (void) G_GNUC_CONST; @@ -71,7 +71,7 @@ void e_mail_account_manager_add_account (EMailAccountManager *manager); void e_mail_account_manager_edit_account (EMailAccountManager *manager, - EAccount *account); + ESource *source); G_END_DECLS diff --git a/mail/e-mail-account-store.c b/mail/e-mail-account-store.c index 2dac692d82..1c5dedf52e 100644 --- a/mail/e-mail-account-store.c +++ b/mail/e-mail-account-store.c @@ -23,11 +23,11 @@ #include <glib/gi18n-lib.h> #include <libebackend/e-extensible.h> +#include <libedataserver/e-source-collection.h> #include <e-util/e-marshal.h> #include <libevolution-utils/e-alert-dialog.h> -#include <libemail-utils/e-account-utils.h> #include <libemail-engine/mail-ops.h> #include <mail/mail-vfolder-ui.h> @@ -101,24 +101,6 @@ index_item_free (IndexItem *item) g_slice_free (IndexItem, item); } -static void -mail_account_store_save_default (EMailAccountStore *store) -{ - EAccountList *account_list; - EAccount *account; - CamelService *service; - const gchar *uid; - - service = e_mail_account_store_get_default_service (store); - - account_list = e_get_account_list (); - uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); - g_return_if_fail (account != NULL); - - e_account_list_set_default (account_list, account); -} - static gboolean mail_account_store_get_iter (EMailAccountStore *store, CamelService *service, @@ -238,6 +220,46 @@ mail_account_store_service_notify_cb (CamelService *service, } static void +mail_account_store_remove_source_cb (ESource *source, + GAsyncResult *result, + EMailAccountStore *store) +{ + GError *error = NULL; + + /* FIXME EMailAccountStore should implement EAlertSink. */ + if (!e_source_remove_finish (source, result, &error)) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } + + g_return_if_fail (store->priv->busy_count > 0); + store->priv->busy_count--; + g_object_notify (G_OBJECT (store), "busy"); + + g_object_unref (store); +} + +static void +mail_account_store_write_source_cb (ESource *source, + GAsyncResult *result, + EMailAccountStore *store) +{ + GError *error = NULL; + + /* FIXME EMailAccountStore should implement EAlertSink. */ + if (!e_source_write_finish (source, result, &error)) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } + + g_return_if_fail (store->priv->busy_count > 0); + store->priv->busy_count--; + g_object_notify (G_OBJECT (store), "busy"); + + g_object_unref (store); +} + +static void mail_account_store_clean_index (EMailAccountStore *store) { GQueue trash = G_QUEUE_INIT; @@ -427,23 +449,34 @@ static void mail_account_store_constructed (GObject *object) { EMailAccountStore *store; + EMailSession *session; + ESourceRegistry *registry; const gchar *config_dir; /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_account_store_parent_class)->constructed (object); store = E_MAIL_ACCOUNT_STORE (object); + session = e_mail_account_store_get_session (store); + registry = e_mail_session_get_registry (session); + + /* Bind the default mail account ESource to our default + * CamelService, with help from some transform functions. */ + g_object_bind_property_full ( + registry, "default-mail-account", + store, "default-service", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + e_binding_transform_source_to_service, + e_binding_transform_service_to_source, + session, (GDestroyNotify) NULL); + config_dir = mail_session_get_config_dir (); /* XXX Should we take the filename as a constructor property? */ store->priv->sort_order_filename = g_build_filename ( config_dir, "sortorder.ini", NULL); - /* XXX This is kinda lame, but should work until EAccount dies. */ - g_signal_connect ( - object, "notify::default-service", - G_CALLBACK (mail_account_store_save_default), NULL); - e_extensible_load_extensions (E_EXTENSIBLE (object)); } @@ -458,94 +491,73 @@ static void mail_account_store_service_removed (EMailAccountStore *store, CamelService *service) { - /* XXX On the account-mgmt branch this operation is asynchronous. - * The 'busy_count' is bumped until changes are written back - * to the D-Bus service. For now I guess we'll just block. */ - - EAccountList *account_list; - EAccount *account; EMailSession *session; - MailFolderCache *cache; - CamelProvider *provider; + ESourceRegistry *registry; + ESource *source; const gchar *uid; session = e_mail_account_store_get_session (store); - cache = e_mail_session_get_folder_cache (session); + registry = e_mail_session_get_registry (session); - mail_folder_cache_service_removed (cache, service); - - account_list = e_get_account_list (); uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); - g_return_if_fail (account != NULL); - - /* no change */ - if (!account->enabled) - return; - - provider = camel_service_get_provider (service); - g_return_if_fail (provider != NULL); - - if (provider->flags & CAMEL_PROVIDER_IS_STORAGE) - mail_disconnect_store (CAMEL_STORE (service)); + source = e_source_registry_ref_source (registry, uid); + + /* If this ESource is part of a collection, we need to remove + * the entire collection. Check the ESource and its ancestors + * for a collection extension and remove the containing source. */ + if (source != NULL) { + ESource *collection; + + collection = e_source_registry_find_extension ( + registry, source, E_SOURCE_EXTENSION_COLLECTION); + if (collection != NULL) { + g_object_unref (source); + source = collection; + } + } - /* Remove all the proxies the account has created. - * FIXME This proxy stuff belongs in evolution-groupwise. */ - e_account_list_remove_account_proxies (account_list, account); + if (source != NULL) { + store->priv->busy_count++; + g_object_notify (G_OBJECT (store), "busy"); - e_account_list_remove (account_list, account); + /* XXX Should this be cancellable? */ + e_source_remove ( + source, NULL, (GAsyncReadyCallback) + mail_account_store_remove_source_cb, + g_object_ref (store)); - e_account_list_save (account_list); + g_object_unref (source); + } } static void mail_account_store_service_enabled (EMailAccountStore *store, CamelService *service) { - /* XXX On the account-mgmt branch this operation is asynchronous. - * The 'busy_count' is bumped until changes are written back - * to the D-Bus service. For now I guess we'll just block. */ - EMailSession *session; - MailFolderCache *cache; - GSettings *settings; + ESourceRegistry *registry; + ESource *source; const gchar *uid; session = e_mail_account_store_get_session (store); - cache = e_mail_session_get_folder_cache (session); - - mail_folder_cache_service_enabled (cache, service); + registry = e_mail_session_get_registry (session); uid = camel_service_get_uid (service); + source = e_source_registry_ref_source (registry, uid); - /* Handle built-in services that don't have an EAccount. */ + if (source != NULL) { + e_source_set_enabled (source, TRUE); - if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) { - settings = g_settings_new ("org.gnome.evolution.mail"); - g_settings_set_boolean (settings, "enable-local", TRUE); - g_object_unref (settings); - - } else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) { - settings = g_settings_new ("org.gnome.evolution.mail"); - g_settings_set_boolean (settings, "enable-vfolders", TRUE); - g_object_unref (settings); - - } else { - EAccountList *account_list; - EAccount *account; - - account_list = e_get_account_list (); - account = e_get_account_by_uid (uid); - g_return_if_fail (account != NULL); - - /* no change */ - if (account->enabled) - return; + store->priv->busy_count++; + g_object_notify (G_OBJECT (store), "busy"); - account->enabled = TRUE; + /* XXX Should this be cancellable? */ + e_source_write ( + source, NULL, (GAsyncReadyCallback) + mail_account_store_write_source_cb, + g_object_ref (store)); - e_account_list_change (account_list, account); - e_account_list_save (account_list); + g_object_unref (source); } } @@ -553,63 +565,30 @@ static void mail_account_store_service_disabled (EMailAccountStore *store, CamelService *service) { - /* XXX On the account-mgmt branch this operation is asynchronous. - * The 'busy_count' is bumped until changes are written back - * to the D-Bus service. For now I guess we'll just block. */ - EMailSession *session; - MailFolderCache *cache; - GSettings *settings; + ESourceRegistry *registry; + ESource *source; const gchar *uid; session = e_mail_account_store_get_session (store); - cache = e_mail_session_get_folder_cache (session); - - mail_folder_cache_service_disabled (cache, service); + registry = e_mail_session_get_registry (session); uid = camel_service_get_uid (service); + source = e_source_registry_ref_source (registry, uid); - /* Handle built-in services that don't have an EAccount. */ + if (source != NULL) { + e_source_set_enabled (source, FALSE); - if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) { - settings = g_settings_new ("org.gnome.evolution.mail"); - g_settings_set_boolean (settings, "enable-local", FALSE); - g_object_unref (settings); - - } else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) { - settings = g_settings_new ("org.gnome.evolution.mail"); - g_settings_set_boolean (settings, "enable-vfolders", FALSE); - g_object_unref (settings); - - } else { - EAccountList *account_list; - EAccount *account; - CamelProvider *provider; + store->priv->busy_count++; + g_object_notify (G_OBJECT (store), "busy"); - account_list = e_get_account_list (); - account = e_get_account_by_uid (uid); - g_return_if_fail (account != NULL); + /* XXX Should this be cancellable? */ + e_source_write ( + source, NULL, (GAsyncReadyCallback) + mail_account_store_write_source_cb, + g_object_ref (store)); - /* no change */ - if (!account->enabled) - return; - - account->enabled = FALSE; - - provider = camel_service_get_provider (service); - g_return_if_fail (provider != NULL); - - if (provider->flags & CAMEL_PROVIDER_IS_STORAGE) - mail_disconnect_store (CAMEL_STORE (service)); - - /* FIXME This proxy stuff belongs in evolution-groupwise. */ - e_account_list_remove_account_proxies (account_list, account); - - if (account->parent_uid != NULL) - e_account_list_remove (account_list, account); - - e_account_list_change (account_list, account); - e_account_list_save (account_list); + g_object_unref (source); } } @@ -643,25 +622,14 @@ mail_account_store_remove_requested (EMailAccountStore *store, GtkWindow *parent_window, CamelService *service) { - EAccountList *account_list; - EAccount *account; - const gchar *alert; - const gchar *uid; gint response; - account_list = e_get_account_list (); - uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); - - g_return_val_if_fail (account != NULL, FALSE); + /* FIXME Need to use "mail:ask-delete-account-with-proxies" if the + * mail account has proxies. But this is groupwise-specific + * and doesn't belong here anyway. Think of a better idea. */ - /* FIXME This proxy stuff belongs in evolution-groupwise. */ - if (e_account_list_account_has_proxies (account_list, account)) - alert = "mail:ask-delete-account-with-proxies"; - else - alert = "mail:ask-delete-account"; - - response = e_alert_run_dialog_for_args (parent_window, alert, NULL); + response = e_alert_run_dialog_for_args ( + parent_window, "mail:ask-delete-account", NULL); return (response == GTK_RESPONSE_YES); } @@ -679,34 +647,12 @@ mail_account_store_disable_requested (EMailAccountStore *store, GtkWindow *parent_window, CamelService *service) { - EAccountList *account_list; - EAccount *account; - const gchar *uid; - gint response; - - account_list = e_get_account_list (); - uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); - - /* "On This Computer" and "Search Folders" do not have - * EAccounts, so just silently return TRUE if we failed - * to find a matching EAccount for the CamelService. */ - - /* Silently return TRUE if we failed to find a matching - * EAccount since "On This Computer" and "Search Folders" - * do not have EAccounts. */ - if (account == NULL) - return TRUE; + /* FIXME Need to check whether the account has proxies and run a + * "mail:ask-delete-proxy-accounts" alert dialog, but this + * is groupwise-specific and doesn't belong here anyway. + * Think of a better idea. */ - /* FIXME This proxy stuff belongs in evolution-groupwise. */ - if (e_account_list_account_has_proxies (account_list, account)) - response = e_alert_run_dialog_for_args ( - parent_window, - "mail:ask-delete-proxy-accounts", NULL); - else - response = GTK_RESPONSE_YES; - - return (response == GTK_RESPONSE_YES); + return TRUE; } static void @@ -1086,13 +1032,20 @@ e_mail_account_store_add_service (EMailAccountStore *store, g_object_unref (settings); } else { - EAccount *account; + EMailSession *session; + ESourceRegistry *registry; + ESource *source; + + session = e_mail_account_store_get_session (store); - account = e_get_account_by_uid (uid); - g_return_if_fail (account != NULL); + registry = e_mail_session_get_registry (session); + source = e_source_registry_ref_source (registry, uid); + g_return_if_fail (source != NULL); builtin = FALSE; - enabled = account->enabled; + enabled = e_source_get_enabled (source); + + g_object_unref (source); } /* Where do we insert new services now that accounts can be diff --git a/mail/e-mail-autoconfig.c b/mail/e-mail-autoconfig.c new file mode 100644 index 0000000000..e3588a8964 --- /dev/null +++ b/mail/e-mail-autoconfig.c @@ -0,0 +1,883 @@ +/* + * e-mail-autoconfig.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-autoconfig.h" + +#include <config.h> +#include <string.h> +#include <glib/gi18n-lib.h> + +/* Stuff for DNS querying and message parsing. */ +#include <netdb.h> +#include <netinet/in.h> +#include <resolv.h> +#include <arpa/nameser.h> +#if defined(HAVE_ARPA_NAMESER_COMPAT_H) && !defined(GETSHORT) +#include <arpa/nameser_compat.h> +#endif + +/* For error codes. */ +#include <libsoup/soup.h> + +#include <libedataserver/e-source-camel.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-transport.h> + +#define E_MAIL_AUTOCONFIG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfigPrivate)) + +#define AUTOCONFIG_BASE_URI \ + "http://api.gnome.org/evolution/autoconfig/1.1/" + +/* XXX g_file_load_contents() on an "http://" URI returns error codes + * in the SOUP_HTTP_ERROR domain instead of the G_IO_ERROR domain. + * That is both undocumented and unexpected. */ +#define ERROR_IS_NOT_FOUND(error) \ + (g_error_matches ((error), SOUP_HTTP_ERROR, SOUP_STATUS_NOT_FOUND)) + +typedef struct _ParserClosure ParserClosure; +typedef struct _ResolverClosure ResolverClosure; + +struct _EMailAutoconfigPrivate { + gchar *email_address; + gchar *email_local_part; + gchar *email_domain_part; + gchar *markup_content; +}; + +struct _ParserClosure { + CamelNetworkSettings *network_settings; + const gchar *expected_type; + const gchar *email_address; + const gchar *email_local_part; + const gchar *email_domain_part; + gboolean in_server_element; + gboolean settings_modified; +}; + +struct _ResolverClosure { + volatile gint ref_count; + GMainContext *main_context; + GMainLoop *main_loop; + gchar *domain_name; + gchar *name_server; + GError *error; +}; + +enum { + PROP_0, + PROP_EMAIL_ADDRESS +}; + +/* Forward Declarations */ +static void e_mail_autoconfig_initable_init (GInitableIface *interface); + +/* By default, the GAsyncInitable interface calls GInitable.init() + * from a separate thread, so we only have to override GInitable. */ +G_DEFINE_TYPE_WITH_CODE ( + EMailAutoconfig, + e_mail_autoconfig, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE ( + G_TYPE_INITABLE, e_mail_autoconfig_initable_init) + G_IMPLEMENT_INTERFACE ( + G_TYPE_ASYNC_INITABLE, NULL)) + +static ResolverClosure * +resolver_closure_new (const gchar *domain_name) +{ + ResolverClosure *closure; + + closure = g_slice_new0 (ResolverClosure); + closure->domain_name = g_strdup (domain_name); + closure->main_context = g_main_context_new (); + closure->main_loop = g_main_loop_new (closure->main_context, FALSE); + closure->ref_count = 1; + + return closure; +} + +static ResolverClosure * +resolver_closure_ref (ResolverClosure *closure) +{ + g_return_val_if_fail (closure != NULL, NULL); + g_return_val_if_fail (closure->ref_count > 0, NULL); + + g_atomic_int_inc (&closure->ref_count); + + return closure; +} + +static void +resolver_closure_unref (ResolverClosure *closure) +{ + g_return_if_fail (closure != NULL); + g_return_if_fail (closure->ref_count > 0); + + if (g_atomic_int_dec_and_test (&closure->ref_count)) { + g_main_context_unref (closure->main_context); + g_main_loop_unref (closure->main_loop); + g_free (closure->domain_name); + g_free (closure->name_server); + g_clear_error (&closure->error); + g_slice_free (ResolverClosure, closure); + } +} + +static gboolean +mail_autoconfig_resolver_idle_quit (gpointer user_data) +{ + GMainLoop *main_loop = user_data; + + g_main_loop_quit (main_loop); + + return FALSE; +} + +static void +mail_autoconfig_resolver_cancelled (GCancellable *cancellable, + ResolverClosure *closure) +{ + GSource *source; + + source = g_idle_source_new (); + g_source_set_callback ( + source, + mail_autoconfig_resolver_idle_quit, + g_main_loop_ref (closure->main_loop), + (GDestroyNotify) g_main_loop_unref); + g_source_attach (source, closure->main_context); + g_source_unref (source); +} + +static gpointer +mail_autoconfig_resolver_thread (gpointer user_data) +{ + ResolverClosure *closure = user_data; + HEADER *header; + guchar answer[1024]; + gchar namebuf[1024]; + guchar *end, *cp; + gint count; + gint length; + gint herr; + + /* Query DNS for the MX record for the domain name given in the + * email address. We need an authoritative name server for it. */ + + length = res_query ( + closure->domain_name, C_IN, T_MX, + answer, sizeof (answer)); + herr = h_errno; /* h_errno is defined in <netdb.h> */ + + /* Based heavily on _g_resolver_targets_from_res_query(). + * The binary DNS message format is described in RFC 1035. */ + + if (length <= 0) { + if (length == 0 || herr == HOST_NOT_FOUND || herr == NO_DATA) + g_set_error ( + &closure->error, + G_RESOLVER_ERROR, + G_RESOLVER_ERROR_NOT_FOUND, + _("No mail exchanger record for '%s'"), + closure->domain_name); + else if (herr == TRY_AGAIN) + g_set_error ( + &closure->error, + G_RESOLVER_ERROR, + G_RESOLVER_ERROR_TEMPORARY_FAILURE, + _("Temporarily unable to resolve '%s'"), + closure->domain_name); + else + g_set_error ( + &closure->error, + G_RESOLVER_ERROR, + G_RESOLVER_ERROR_INTERNAL, + _("Error resolving '%s'"), + closure->domain_name); + goto exit; + } + + header = (HEADER *) answer; + cp = answer + sizeof (HEADER); + end = answer + length; + + /* Skip the 'question' section. */ + count = ntohs (header->qdcount); + while (count-- && cp < end) { + cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf)); + cp += 2; /* skip QTYPE */ + cp += 2; /* skip QCLASS */ + } + + /* Skip the 'answers' section. */ + count = ntohs (header->ancount); + while (count-- && cp < end) { + guint16 rdlength; + cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf)); + cp += 2; /* skip TYPE */ + cp += 2; /* skip CLASS */ + cp += 4; /* skip TTL */ + GETSHORT (rdlength, cp); /* read RDLENGTH */ + cp += rdlength; /* skip RDATA */ + } + + /* Read the 'authority' section. */ + count = ntohs (header->nscount); + while (count-- && cp < end) { + guint16 type, qclass, rdlength; + cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf)); + GETSHORT (type, cp); + GETSHORT (qclass, cp); + cp += 4; /* skip TTL */ + GETSHORT (rdlength, cp); + + if (type != T_NS || qclass != C_IN) { + cp += rdlength; + continue; + } + + cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf)); + + /* Pick the first T_NS record we find. */ + closure->name_server = g_strdup (namebuf); + break; + } + + if (closure->name_server == NULL) + g_set_error ( + &closure->error, + G_RESOLVER_ERROR, + G_RESOLVER_ERROR_NOT_FOUND, + _("No authoritative name server for '%s'"), + closure->domain_name); + +exit: + g_main_loop_quit (closure->main_loop); + resolver_closure_unref (closure); + + return NULL; /* return value is not used */ +} + +static gchar * +mail_autoconfig_resolve_authority (const gchar *domain, + GCancellable *cancellable, + GError **error) +{ + ResolverClosure *closure; + GThread *resolver_thread; + gchar *name_server = NULL; + gulong cancel_id = 0; + + closure = resolver_closure_new (domain); + + /* DNS record lookup is not cancellable, so we run it in a + * separate thread. We don't join with the thread, however, + * because if we get cancelled we want to return immediately. + * So use a reference count on the thread closure and always + * let the thread run to completion even if we're not around + * any longer to pick up the result. */ + resolver_thread = g_thread_create ( + mail_autoconfig_resolver_thread, + resolver_closure_ref (closure), + FALSE /* not joinable */, error); + + if (resolver_thread == NULL) + return FALSE; + + if (G_IS_CANCELLABLE (cancellable)) + cancel_id = g_cancellable_connect ( + cancellable, + G_CALLBACK (mail_autoconfig_resolver_cancelled), + resolver_closure_ref (closure), + (GDestroyNotify) resolver_closure_unref); + + g_main_loop_run (closure->main_loop); + + if (cancel_id > 0) + g_cancellable_disconnect (cancellable, cancel_id); + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) { + /* do nothing */ + + } else if (closure->error != NULL) { + g_warn_if_fail (closure->name_server == NULL); + g_propagate_error (error, closure->error); + closure->error = NULL; + + } else { + g_warn_if_fail (closure->name_server != NULL); + name_server = closure->name_server; + closure->name_server = NULL; + } + + resolver_closure_unref (closure); + + return name_server; +} + +static gboolean +mail_autoconfig_lookup (EMailAutoconfig *autoconfig, + const gchar *domain, + GCancellable *cancellable, + GError **error) +{ + GFile *file; + gchar *uri; + gboolean success; + + uri = g_strconcat (AUTOCONFIG_BASE_URI, domain, NULL); + file = g_file_new_for_uri (uri); + g_free (uri); + + /* Just to make sure we don't leak. */ + g_free (autoconfig->priv->markup_content); + autoconfig->priv->markup_content = NULL; + + success = g_file_load_contents ( + file, cancellable, + &autoconfig->priv->markup_content, + NULL, NULL, error); + + g_object_unref (file); + + return success; +} + +static void +mail_autoconfig_parse_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ParserClosure *closure = user_data; + gboolean is_incoming_server; + gboolean is_outgoing_server; + + is_incoming_server = g_str_equal (element_name, "incomingServer"); + is_outgoing_server = g_str_equal (element_name, "outgoingServer"); + + if (is_incoming_server || is_outgoing_server) { + const gchar *type = NULL; + + g_markup_collect_attributes ( + element_name, + attribute_names, + attribute_values, + error, + G_MARKUP_COLLECT_STRING, + "type", &type, + G_MARKUP_COLLECT_INVALID); + + closure->in_server_element = + (g_strcmp0 (type, closure->expected_type) == 0); + } +} + +static void +mail_autoconfig_parse_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + ParserClosure *closure = user_data; + gboolean is_incoming_server; + gboolean is_outgoing_server; + + is_incoming_server = g_str_equal (element_name, "incomingServer"); + is_outgoing_server = g_str_equal (element_name, "outgoingServer"); + + if (is_incoming_server || is_outgoing_server) + closure->in_server_element = FALSE; +} + +static void +mail_autoconfig_parse_text (GMarkupParseContext *context, + const gchar *text, + gsize text_length, + gpointer user_data, + GError **error) +{ + ParserClosure *closure = user_data; + const gchar *element_name; + GString *string; + + if (!closure->in_server_element) + return; + + /* Perform the following text substitutions: + * + * %EMAILADDRESS% : closure->email_address + * %EMAILLOCALPART% : closure->email_local_part + * %EMAILDOMAIN% : closure->email_domain_part + */ + if (strchr (text, '%') == NULL) + string = g_string_new (text); + else { + const gchar *cp = text; + + string = g_string_sized_new (256); + while (*cp != '\0') { + const gchar *variable; + const gchar *substitute; + + if (*cp != '%') { + g_string_append_c (string, *cp++); + continue; + } + + variable = "%EMAILADDRESS%"; + substitute = closure->email_address; + + if (strncmp (cp, variable, strlen (variable)) == 0) { + g_string_append (string, substitute); + cp += strlen (variable); + continue; + } + + variable = "%EMAILLOCALPART%"; + substitute = closure->email_local_part; + + if (strncmp (cp, variable, strlen (variable)) == 0) { + g_string_append (string, substitute); + cp += strlen (variable); + continue; + } + + variable = "%EMAILDOMAIN%"; + substitute = closure->email_domain_part; + + if (strncmp (cp, variable, strlen (variable)) == 0) { + g_string_append (string, substitute); + cp += strlen (variable); + continue; + } + + g_string_append_c (string, *cp++); + } + } + + element_name = g_markup_parse_context_get_element (context); + + if (g_str_equal (element_name, "hostname")) { + camel_network_settings_set_host ( + closure->network_settings, string->str); + closure->settings_modified = TRUE; + + } else if (g_str_equal (element_name, "username")) { + camel_network_settings_set_user ( + closure->network_settings, string->str); + closure->settings_modified = TRUE; + + } else if (g_str_equal (element_name, "port")) { + glong port = strtol (string->str, NULL, 10); + if (port == CLAMP (port, 1, G_MAXUINT16)) { + camel_network_settings_set_port ( + closure->network_settings, (guint16) port); + closure->settings_modified = TRUE; + } + + } else if (g_str_equal (element_name, "socketType")) { + if (g_str_equal (string->str, "plain")) { + camel_network_settings_set_security_method ( + closure->network_settings, + CAMEL_NETWORK_SECURITY_METHOD_NONE); + closure->settings_modified = TRUE; + } else if (g_str_equal (string->str, "SSL")) { + camel_network_settings_set_security_method ( + closure->network_settings, + CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT); + closure->settings_modified = TRUE; + } else if (g_str_equal (string->str, "STARTTLS")) { + camel_network_settings_set_security_method ( + closure->network_settings, + CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT); + closure->settings_modified = TRUE; + } + } + + /* FIXME Not handling <authentication> elements. + * Unclear how some map to SASL mechanisms. */ + + g_string_free (string, TRUE); +} + +static GMarkupParser mail_autoconfig_parser = { + mail_autoconfig_parse_start_element, + mail_autoconfig_parse_end_element, + mail_autoconfig_parse_text +}; + +static gboolean +mail_autoconfig_set_details (EMailAutoconfig *autoconfig, + const gchar *expected_type, + ESource *source, + const gchar *extension_name) +{ + GMarkupParseContext *context; + ESourceCamel *camel_ext; + ESourceBackend *backend_ext; + CamelSettings *settings; + ParserClosure closure; + const gchar *backend_name; + const gchar *markup_content; + gboolean success; + + if (!e_source_has_extension (source, extension_name)) + return FALSE; + + backend_ext = e_source_get_extension (source, extension_name); + backend_name = e_source_backend_get_backend_name (backend_ext); + extension_name = e_source_camel_get_extension_name (backend_name); + camel_ext = e_source_get_extension (source, extension_name); + + settings = e_source_camel_get_settings (camel_ext); + g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), FALSE); + + markup_content = e_mail_autoconfig_get_markup_content (autoconfig); + g_return_val_if_fail (markup_content != NULL, FALSE); + + closure.network_settings = CAMEL_NETWORK_SETTINGS (settings); + closure.expected_type = expected_type; + closure.in_server_element = FALSE; + closure.settings_modified = FALSE; + + /* These are used for text substitutions. */ + closure.email_address = autoconfig->priv->email_address; + closure.email_local_part = autoconfig->priv->email_local_part; + closure.email_domain_part = autoconfig->priv->email_domain_part; + + context = g_markup_parse_context_new ( + &mail_autoconfig_parser, 0, &closure, (GDestroyNotify) NULL); + + success = g_markup_parse_context_parse ( + context, markup_content, strlen (markup_content), NULL); + + success &= g_markup_parse_context_end_parse (context, NULL); + + /* Did we actually configure anything? */ + success &= closure.settings_modified; + + g_markup_parse_context_free (context); + + return success; +} + +static void +mail_autoconfig_set_email_address (EMailAutoconfig *autoconfig, + const gchar *email_address) +{ + g_return_if_fail (email_address != NULL); + g_return_if_fail (autoconfig->priv->email_address == NULL); + + autoconfig->priv->email_address = g_strdup (email_address); +} + +static void +mail_autoconfig_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_EMAIL_ADDRESS: + mail_autoconfig_set_email_address ( + E_MAIL_AUTOCONFIG (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_autoconfig_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_EMAIL_ADDRESS: + g_value_set_string ( + value, + e_mail_autoconfig_get_email_address ( + E_MAIL_AUTOCONFIG (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_autoconfig_finalize (GObject *object) +{ + EMailAutoconfigPrivate *priv; + + priv = E_MAIL_AUTOCONFIG_GET_PRIVATE (object); + + g_free (priv->email_address); + g_free (priv->email_local_part); + g_free (priv->email_domain_part); + g_free (priv->markup_content); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_autoconfig_parent_class)->finalize (object); +} + +static gboolean +mail_autoconfig_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + EMailAutoconfig *autoconfig; + const gchar *email_address; + const gchar *domain; + const gchar *cp; + gchar *name_server; + gboolean success = FALSE; + GError *local_error = NULL; + + autoconfig = E_MAIL_AUTOCONFIG (initable); + email_address = e_mail_autoconfig_get_email_address (autoconfig); + + if (email_address == NULL) { + g_set_error_literal ( + error, G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("No email address provided")); + return FALSE; + } + + cp = strchr (email_address, '@'); + if (cp == NULL) { + g_set_error_literal ( + error, G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Missing domain in email address")); + return FALSE; + } + + domain = cp + 1; + + autoconfig->priv->email_local_part = + g_strndup (email_address, cp - email_address); + autoconfig->priv->email_domain_part = g_strdup (domain); + + /* First try the email address domain verbatim. */ + success = mail_autoconfig_lookup ( + autoconfig, domain, cancellable, &local_error); + + g_warn_if_fail ( + (success && local_error == NULL) || + (!success && local_error != NULL)); + + if (success) + return TRUE; + + /* "404 Not Found" errors are non-fatal this time around. */ + if (ERROR_IS_NOT_FOUND (local_error)) { + g_clear_error (&local_error); + } else { + g_propagate_error (error, local_error); + return FALSE; + } + + /* Look up an authoritative name server for the email address + * domain according to its "mail exchanger" (MX) DNS record. */ + name_server = mail_autoconfig_resolve_authority ( + domain, cancellable, error); + + if (name_server == NULL) + return FALSE; + + /* Widdle away segments of the name server domain until + * we find a match, or until we widdle down to nothing. */ + + cp = name_server; + while (cp != NULL && strchr (cp, '.') != NULL) { + g_clear_error (&local_error); + + success = mail_autoconfig_lookup ( + autoconfig, cp, cancellable, &local_error); + + g_warn_if_fail ( + (success && local_error == NULL) || + (!success && local_error != NULL)); + + if (success || !ERROR_IS_NOT_FOUND (local_error)) + break; + + cp = strchr (cp, '.'); + if (cp != NULL) + cp++; + } + + if (local_error != NULL) + g_propagate_error (error, local_error); + + g_free (name_server); + + return success; +} + +static void +e_mail_autoconfig_class_init (EMailAutoconfigClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailAutoconfigPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_autoconfig_set_property; + object_class->get_property = mail_autoconfig_get_property; + object_class->finalize = mail_autoconfig_finalize; + + g_object_class_install_property ( + object_class, + PROP_EMAIL_ADDRESS, + g_param_spec_string ( + "email-address", + "Email Address", + "The address from which to query config data", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_autoconfig_initable_init (GInitableIface *interface) +{ + interface->init = mail_autoconfig_initable_init; +} + +static void +e_mail_autoconfig_init (EMailAutoconfig *autoconfig) +{ + autoconfig->priv = E_MAIL_AUTOCONFIG_GET_PRIVATE (autoconfig); +} + +EMailAutoconfig * +e_mail_autoconfig_new_sync (const gchar *email_address, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (email_address != NULL, NULL); + + return g_initable_new ( + E_TYPE_MAIL_AUTOCONFIG, + cancellable, error, + "email-address", email_address, + NULL); +} + +void +e_mail_autoconfig_new (const gchar *email_address, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (email_address != NULL); + + g_async_initable_new_async ( + E_TYPE_MAIL_AUTOCONFIG, + io_priority, cancellable, + callback, user_data, + "email-address", email_address, + NULL); +} + +EMailAutoconfig * +e_mail_autoconfig_finish (GAsyncResult *result, + GError **error) +{ + GObject *source_object; + GObject *autoconfig; + + g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL); + + source_object = g_async_result_get_source_object (result); + g_return_val_if_fail (source_object != NULL, NULL); + + autoconfig = g_async_initable_new_finish ( + G_ASYNC_INITABLE (source_object), result, error); + + g_object_unref (source_object); + + if (autoconfig == NULL) + return NULL; + + return E_MAIL_AUTOCONFIG (autoconfig); +} + +const gchar * +e_mail_autoconfig_get_email_address (EMailAutoconfig *autoconfig) +{ + g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), NULL); + + return autoconfig->priv->email_address; +} + +const gchar * +e_mail_autoconfig_get_markup_content (EMailAutoconfig *autoconfig) +{ + g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), NULL); + + return autoconfig->priv->markup_content; +} + +gboolean +e_mail_autoconfig_set_imap_details (EMailAutoconfig *autoconfig, + ESource *imap_source) +{ + g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE); + g_return_val_if_fail (E_IS_SOURCE (imap_source), FALSE); + + return mail_autoconfig_set_details ( + autoconfig, "imap", imap_source, + E_SOURCE_EXTENSION_MAIL_ACCOUNT); +} + +gboolean +e_mail_autoconfig_set_pop3_details (EMailAutoconfig *autoconfig, + ESource *pop3_source) +{ + g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE); + g_return_val_if_fail (E_IS_SOURCE (pop3_source), FALSE); + + return mail_autoconfig_set_details ( + autoconfig, "pop3", pop3_source, + E_SOURCE_EXTENSION_MAIL_ACCOUNT); +} + +gboolean +e_mail_autoconfig_set_smtp_details (EMailAutoconfig *autoconfig, + ESource *smtp_source) +{ + g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE); + g_return_val_if_fail (E_IS_SOURCE (smtp_source), FALSE); + + return mail_autoconfig_set_details ( + autoconfig, "smtp", smtp_source, + E_SOURCE_EXTENSION_MAIL_TRANSPORT); +} + diff --git a/mail/e-mail-autoconfig.h b/mail/e-mail-autoconfig.h new file mode 100644 index 0000000000..5b03ace7a3 --- /dev/null +++ b/mail/e-mail-autoconfig.h @@ -0,0 +1,89 @@ +/* + * e-mail-autoconfig.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_AUTOCONFIG_H +#define E_MAIL_AUTOCONFIG_H + +#include <gio/gio.h> +#include <libedataserver/e-source.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_AUTOCONFIG \ + (e_mail_autoconfig_get_type ()) +#define E_MAIL_AUTOCONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfig)) +#define E_MAIL_AUTOCONFIG_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfigClass)) +#define E_IS_MAIL_AUTOCONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_AUTOCONFIG)) +#define E_IS_MAIL_AUTOCONFIG_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_AUTOCONFIG)) +#define E_MAIL_AUTOCONFIG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfigClass)) + +G_BEGIN_DECLS + +typedef struct _EMailAutoconfig EMailAutoconfig; +typedef struct _EMailAutoconfigClass EMailAutoconfigClass; +typedef struct _EMailAutoconfigPrivate EMailAutoconfigPrivate; + +struct _EMailAutoconfig { + GObject parent; + EMailAutoconfigPrivate *priv; +}; + +struct _EMailAutoconfigClass { + GObjectClass parent_class; +}; + +GType e_mail_autoconfig_get_type (void) G_GNUC_CONST; +EMailAutoconfig * + e_mail_autoconfig_new_sync (const gchar *email_address, + GCancellable *cancellable, + GError **error); +void e_mail_autoconfig_new (const gchar *email_address, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +EMailAutoconfig * + e_mail_autoconfig_finish (GAsyncResult *result, + GError **error); +const gchar * e_mail_autoconfig_get_email_address + (EMailAutoconfig *autoconfig); +const gchar * e_mail_autoconfig_get_markup_content + (EMailAutoconfig *autoconfig); +gboolean e_mail_autoconfig_set_imap_details + (EMailAutoconfig *autoconfig, + ESource *imap_source); +gboolean e_mail_autoconfig_set_pop3_details + (EMailAutoconfig *autoconfig, + ESource *pop3_source); +gboolean e_mail_autoconfig_set_smtp_details + (EMailAutoconfig *autoconfig, + ESource *smtp_source); + +G_END_DECLS + +#endif /* E_MAIL_AUTOCONFIG_H */ + diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c index c350bd7b5d..60e506d09d 100644 --- a/mail/e-mail-backend.c +++ b/mail/e-mail-backend.c @@ -32,15 +32,15 @@ #include <glib/gstdio.h> #include <glib/gi18n-lib.h> #include <libedataserver/e-data-server-util.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-composition.h> +#include <libedataserver/e-source-mail-submission.h> #include <shell/e-shell.h> #include <libevolution-utils/e-alert-dialog.h> #include <libevolution-utils/e-alert-sink.h> -#include <misc/e-account-combo-box.h> - -#include <libemail-utils/e-account-utils.h> #include <libemail-engine/e-mail-folder-utils.h> #include <libemail-engine/e-mail-session.h> #include <libemail-engine/e-mail-store-utils.h> @@ -141,11 +141,14 @@ mail_backend_prepare_for_offline_cb (EShell *shell, { GtkWindow *window; EMailSession *session; + ESourceRegistry *registry; GList *list, *link; + const gchar *extension_name; gboolean synchronize = FALSE; window = e_shell_get_active_window (shell); session = e_mail_backend_get_session (backend); + registry = e_mail_session_get_registry (session); if (e_shell_get_network_available (shell) && e_shell_backend_is_started (E_SHELL_BACKEND (backend))) @@ -158,12 +161,17 @@ mail_backend_prepare_for_offline_cb (EShell *shell, CAMEL_SESSION (session), FALSE); } - list = camel_session_list_services (CAMEL_SESSION (session)); + 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)) { + ESource *source = E_SOURCE (link->data); CamelService *service; + const gchar *uid; - service = CAMEL_SERVICE (link->data); + uid = e_source_get_uid (source); + service = camel_session_get_service ( + CAMEL_SESSION (session), uid); if (!CAMEL_IS_STORE (service)) continue; @@ -176,7 +184,7 @@ mail_backend_prepare_for_offline_cb (EShell *shell, g_object_ref (activity)); } - g_list_free (list); + g_list_free_full (list, (GDestroyNotify) g_object_unref); } static void @@ -185,27 +193,31 @@ mail_backend_prepare_for_online_cb (EShell *shell, EMailBackend *backend) { EMailSession *session; + ESourceRegistry *registry; GList *list, *link; + const gchar *extension_name; session = e_mail_backend_get_session (backend); + registry = e_mail_session_get_registry (session); + camel_session_set_online (CAMEL_SESSION (session), TRUE); - list = camel_session_list_services (CAMEL_SESSION (session)); + 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)) { + ESource *source = E_SOURCE (link->data); CamelService *service; - EAccount *account; const gchar *uid; - service = CAMEL_SERVICE (link->data); - - if (!CAMEL_IS_STORE (service)) + if (!e_source_get_enabled (source)) continue; - uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); + uid = e_source_get_uid (source); + service = camel_session_get_service ( + CAMEL_SESSION (session), uid); - if (account != NULL && !account->enabled) + if (!CAMEL_IS_STORE (service)) continue; /* FIXME Not passing a GCancellable. */ @@ -216,7 +228,7 @@ mail_backend_prepare_for_online_cb (EShell *shell, g_object_ref (activity)); } - g_list_free (link); + g_list_free_full (list, (GDestroyNotify) g_object_unref); } /* Helper for mail_backend_prepare_for_quit_cb() */ @@ -273,7 +285,6 @@ mail_backend_prepare_for_quit_cb (EShell *shell, EActivity *activity, EMailBackend *backend) { - EAccountList *account_list; EMailSession *session; GList *list, *link; gboolean delete_junk; @@ -286,9 +297,6 @@ mail_backend_prepare_for_quit_cb (EShell *shell, camel_application_is_exiting = TRUE; - account_list = e_get_account_list (); - e_account_list_prune_proxies (account_list); - mail_vfolder_shutdown (); /* Cancel all pending activities. */ @@ -399,20 +407,26 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache, const gchar *folder_name, EMailBackend *backend) { + EShell *shell; CamelStoreClass *class; - EAccountList *account_list; - EIterator *iterator; + ESourceRegistry *registry; + EShellBackend *shell_backend; EMailSession *session; EAlertSink *alert_sink; + GList *list, *link; + const gchar *extension_name; const gchar *local_drafts_folder_uri; const gchar *local_sent_folder_uri; - gboolean write_config = FALSE; gchar *uri; /* Check whether the deleted folder was a designated Drafts or * Sent folder for any mail account, and if so revert the setting * to the equivalent local folder, which is always present. */ + shell_backend = E_SHELL_BACKEND (backend); + shell = e_shell_backend_get_shell (shell_backend); + registry = e_shell_get_registry (shell); + class = CAMEL_STORE_GET_CLASS (store); g_return_if_fail (class->compare_folder_name != NULL); @@ -429,51 +443,69 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache, uri = e_mail_folder_uri_build (store, folder_name); - account_list = e_get_account_list (); - iterator = e_list_get_iterator (E_LIST (account_list)); + extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION; + list = e_source_registry_list_sources (registry, extension_name); - while (e_iterator_is_valid (iterator)) { - EAccount *account; + for (link = list; link != NULL; link = g_list_next (link)) { + ESource *source = E_SOURCE (link->data); + ESourceExtension *extension; + const gchar *drafts_folder_uri; + + extension = e_source_get_extension (source, extension_name); - /* XXX EIterator misuses const. */ - account = (EAccount *) e_iterator_get (iterator); + drafts_folder_uri = + e_source_mail_composition_get_drafts_folder ( + E_SOURCE_MAIL_COMPOSITION (extension)); - if (account->sent_folder_uri != NULL) { - gboolean match; + if (class->compare_folder_name (drafts_folder_uri, uri)) { + GError *error = NULL; - match = class->compare_folder_name ( - account->sent_folder_uri, uri); + e_source_mail_composition_set_drafts_folder ( + E_SOURCE_MAIL_COMPOSITION (extension), + local_drafts_folder_uri); - if (match) { - g_free (account->sent_folder_uri); - account->sent_folder_uri = - g_strdup (local_sent_folder_uri); - write_config = TRUE; + /* FIXME This is a blocking D-Bus method call. */ + if (!e_source_write_sync (source, NULL, &error)) { + g_warning ("%s", error->message); + g_error_free (error); } } + } - if (account->drafts_folder_uri != NULL) { - gboolean match; + g_list_free_full (list, (GDestroyNotify) g_object_unref); - match = class->compare_folder_name ( - account->drafts_folder_uri, uri); + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + list = e_source_registry_list_sources (registry, extension_name); - if (match) { - g_free (account->drafts_folder_uri); - account->drafts_folder_uri = - g_strdup (local_drafts_folder_uri); - write_config = TRUE; + for (link = list; link != NULL; link = g_list_next (link)) { + ESource *source = E_SOURCE (link->data); + ESourceExtension *extension; + const gchar *sent_folder_uri; + + extension = e_source_get_extension (source, extension_name); + + sent_folder_uri = + e_source_mail_submission_get_sent_folder ( + E_SOURCE_MAIL_SUBMISSION (extension)); + + if (class->compare_folder_name (sent_folder_uri, uri)) { + GError *error = NULL; + + e_source_mail_submission_set_sent_folder ( + E_SOURCE_MAIL_SUBMISSION (extension), + local_sent_folder_uri); + + /* FIXME This is a blocking D-Bus method call. */ + if (!e_source_write_sync (source, NULL, &error)) { + g_warning ("%s", error->message); + g_error_free (error); } } - - e_iterator_next (iterator); } - g_object_unref (iterator); - g_free (uri); + g_list_free_full (list, (GDestroyNotify) g_object_unref); - if (write_config) - mail_config_write (); + g_free (uri); /* This does something completely different. * XXX Make it a separate signal handler? */ @@ -487,10 +519,12 @@ mail_backend_folder_renamed_cb (MailFolderCache *folder_cache, const gchar *new_folder_name, EMailBackend *backend) { + EShell *shell; CamelStoreClass *class; - EAccountList *account_list; - EIterator *iterator; - gboolean write_config = FALSE; + ESourceRegistry *registry; + EShellBackend *shell_backend; + GList *list, *link; + const gchar *extension_name; gchar *old_uri; gchar *new_uri; gint ii; @@ -500,54 +534,84 @@ mail_backend_folder_renamed_cb (MailFolderCache *folder_cache, "views/custom_view-" }; + /* Check whether the renamed folder was a designated Drafts or + * Sent folder for any mail account, and if so update the setting + * to the new folder name. */ + + shell_backend = E_SHELL_BACKEND (backend); + shell = e_shell_backend_get_shell (shell_backend); + registry = e_shell_get_registry (shell); + class = CAMEL_STORE_GET_CLASS (store); g_return_if_fail (class->compare_folder_name != NULL); old_uri = e_mail_folder_uri_build (store, old_folder_name); new_uri = e_mail_folder_uri_build (store, new_folder_name); - account_list = e_get_account_list (); - iterator = e_list_get_iterator (E_LIST (account_list)); + extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION; + list = e_source_registry_list_sources (registry, extension_name); + + for (link = list; link != NULL; link = g_list_next (link)) { + ESource *source = E_SOURCE (link->data); + ESourceExtension *extension; + const gchar *drafts_folder_uri; - while (e_iterator_is_valid (iterator)) { - EAccount *account; + extension = e_source_get_extension (source, extension_name); - /* XXX EIterator misuses const. */ - account = (EAccount *) e_iterator_get (iterator); + drafts_folder_uri = + e_source_mail_composition_get_drafts_folder ( + E_SOURCE_MAIL_COMPOSITION (extension)); - if (account->sent_folder_uri != NULL) { - gboolean match; + if (class->compare_folder_name (drafts_folder_uri, old_uri)) { + GError *error = NULL; - match = class->compare_folder_name ( - account->sent_folder_uri, old_uri); + e_source_mail_composition_set_drafts_folder ( + E_SOURCE_MAIL_COMPOSITION (extension), + new_uri); - if (match) { - g_free (account->sent_folder_uri); - account->sent_folder_uri = g_strdup (new_uri); - write_config = TRUE; + /* FIXME This is a blocking D-Bus method call. */ + if (!e_source_write_sync (source, NULL, &error)) { + g_warning ("%s", error->message); + g_error_free (error); } } + } + + g_list_free_full (list, (GDestroyNotify) g_object_unref); - if (account->drafts_folder_uri != NULL) { - gboolean match; + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + list = e_source_registry_list_sources (registry, extension_name); - match = class->compare_folder_name ( - account->drafts_folder_uri, old_uri); + for (link = list; link != NULL; link = g_list_next (link)) { + ESource *source = E_SOURCE (link->data); + ESourceExtension *extension; + const gchar *sent_folder_uri; - if (match) { - g_free (account->drafts_folder_uri); - account->drafts_folder_uri = g_strdup (new_uri); - write_config = TRUE; + extension = e_source_get_extension (source, extension_name); + + sent_folder_uri = + e_source_mail_submission_get_sent_folder ( + E_SOURCE_MAIL_SUBMISSION (extension)); + + if (class->compare_folder_name (sent_folder_uri, old_uri)) { + GError *error = NULL; + + e_source_mail_submission_set_sent_folder ( + E_SOURCE_MAIL_SUBMISSION (extension), + new_uri); + + /* FIXME This is a blocking D-Bus method call. */ + if (!e_source_write_sync (source, NULL, &error)) { + g_warning ("%s", error->message); + g_error_free (error); } } - - e_iterator_next (iterator); } - g_object_unref (iterator); + g_list_free_full (list, (GDestroyNotify) g_object_unref); - if (write_config) - mail_config_write (); + g_free (old_uri); + g_free (new_uri); /* Rename GalView files. */ @@ -565,9 +629,6 @@ mail_backend_folder_renamed_cb (MailFolderCache *folder_cache, g_free (newname); } - g_free (old_uri); - g_free (new_uri); - /* This does something completely different. * XXX Make it a separate signal handler? */ mail_filter_rename_folder ( @@ -606,10 +667,8 @@ mail_backend_folder_changed_cb (MailFolderCache *folder_cache, g_object_unref (folder); } - g_free (folder_uri); - target = em_event_target_new_folder ( - event, store, folder_name, new_messages, + event, store, folder_uri, new_messages, msg_uid, msg_sender, msg_subject); folder_type = (flags & CAMEL_FOLDER_TYPE_MASK); @@ -939,6 +998,7 @@ mail_backend_constructed (GObject *object) EShell *shell; EShellBackend *shell_backend; MailFolderCache *folder_cache; + ESourceRegistry *registry; priv = E_MAIL_BACKEND_GET_PRIVATE (object); @@ -948,9 +1008,8 @@ mail_backend_constructed (GObject *object) if (camel_init (e_get_user_data_dir (), TRUE) != 0) exit (0); - camel_provider_init (); - - priv->session = e_mail_ui_session_new (); + registry = e_shell_get_registry (shell); + priv->session = e_mail_ui_session_new (registry); g_signal_connect ( priv->session, "flush-outbox", @@ -978,10 +1037,6 @@ mail_backend_constructed (GObject *object) G_CALLBACK (mail_backend_job_finished_cb), shell_backend); - /* FIXME This is an evil hack that needs to die. - * Give EAccountComboBox a CamelSession property. */ - e_account_combo_box_set_session (CAMEL_SESSION (priv->session)); - g_signal_connect ( priv->session, "store-added", G_CALLBACK (mail_backend_add_store), @@ -1029,7 +1084,6 @@ mail_backend_constructed (GObject *object) G_CALLBACK (mail_backend_folder_changed_cb), shell_backend); mail_config_init (priv->session); - mail_msg_init (); mail_msg_register_activities ( mail_mt_create_activity, diff --git a/mail/e-mail-config-assistant.c b/mail/e-mail-config-assistant.c new file mode 100644 index 0000000000..e81a1980ce --- /dev/null +++ b/mail/e-mail-config-assistant.c @@ -0,0 +1,1157 @@ +/* + * e-mail-config-assistant.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-config-assistant.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-composition.h> +#include <libedataserver/e-source-mail-identity.h> +#include <libedataserver/e-source-mail-submission.h> +#include <libedataserver/e-source-mail-transport.h> + +#include <libevolution-utils/e-alert-sink.h> + +#include <mail/e-mail-config-confirm-page.h> +#include <mail/e-mail-config-identity-page.h> +#include <mail/e-mail-config-lookup-page.h> +#include <mail/e-mail-config-provider-page.h> +#include <mail/e-mail-config-receiving-page.h> +#include <mail/e-mail-config-sending-page.h> +#include <mail/e-mail-config-summary-page.h> +#include <mail/e-mail-config-welcome-page.h> + +#define E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistantPrivate)) + +struct _EMailConfigAssistantPrivate { + EMailSession *session; + ESource *identity_source; + GPtrArray *account_sources; + GPtrArray *transport_sources; + EMailConfigServicePage *receiving_page; + EMailConfigServicePage *sending_page; + EMailConfigSummaryPage *summary_page; + EMailConfigPage *lookup_page; + GHashTable *visited_pages; + gboolean auto_configure_done; +}; + +enum { + PROP_0, + PROP_ACCOUNT_BACKEND, + PROP_ACCOUNT_SOURCE, + PROP_IDENTITY_SOURCE, + PROP_SESSION, + PROP_TRANSPORT_BACKEND, + PROP_TRANSPORT_SOURCE +}; + +/* XXX We implement EAlertSink but don't implement a custom submit_alert() + * method. So any alert results in a pop-up message dialog, which is a + * fashion faux pas these days. But it's only used when submitting the + * the newly-configured account fails, so should rarely be seen. */ + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigAssistant, + e_mail_config_assistant, + GTK_TYPE_ASSISTANT, + G_IMPLEMENT_INTERFACE ( + E_TYPE_ALERT_SINK, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL)) + +static gint +mail_config_assistant_provider_compare (gconstpointer data1, + gconstpointer data2) +{ + const CamelProvider *provider1 = data1; + const CamelProvider *provider2 = data2; + + /* The "none" provider comes first. */ + if (g_strcmp0 (provider1->protocol, "none") == 0) + return -1; + if (g_strcmp0 (provider2->protocol, "none") == 0) + return 1; + + /* Then sort remote providers before local providers. */ + if (provider1->flags & CAMEL_PROVIDER_IS_REMOTE) { + if (provider2->flags & CAMEL_PROVIDER_IS_REMOTE) + return 0; + else + return -1; + } else { + if (provider2->flags & CAMEL_PROVIDER_IS_REMOTE) + return 1; + else + return 0; + } +} + +static GList * +mail_config_assistant_list_providers (void) +{ + GList *list, *link; + GQueue trash = G_QUEUE_INIT; + + list = camel_provider_list (TRUE); + list = g_list_sort (list, mail_config_assistant_provider_compare); + + /* Keep only providers with a "mail" or "news" domain. */ + + for (link = list; link != NULL; link = g_list_next (link)) { + CamelProvider *provider = link->data; + gboolean mail_or_news_domain; + + mail_or_news_domain = + (g_strcmp0 (provider->domain, "mail") == 0) || + (g_strcmp0 (provider->domain, "news") == 0); + + if (mail_or_news_domain) + continue; + + g_queue_push_tail (&trash, link); + } + + while ((link = g_queue_pop_head (&trash)) != NULL) + list = g_list_remove_link (list, link); + + return list; +} + +static void +mail_config_assistant_notify_account_backend (EMailConfigServicePage *page, + GParamSpec *pspec, + EMailConfigAssistant *assistant) +{ + EMailConfigServiceBackend *backend; + EMailConfigServicePage *sending_page; + EMailConfigServicePageClass *page_class; + CamelProvider *provider; + + backend = e_mail_config_service_page_get_active_backend (page); + + /* The Receiving Page combo box may not have an active item. */ + if (backend == NULL) + goto notify; + + /* The Sending Page may not have been created yet. */ + if (assistant->priv->sending_page == NULL) + goto notify; + + provider = e_mail_config_service_backend_get_provider (backend); + + /* XXX This should never fail, but the Camel macro below does + * not check for NULL so better to malfunction than crash. */ + g_return_if_fail (provider != NULL); + + sending_page = assistant->priv->sending_page; + page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (sending_page); + + /* The Sending Page is invisible when the CamelProvider for the + * receiving type defines both a storage and transport service. + * This is common in CamelProviders for groupware products like + * Microsoft Exchange and Novell GroupWise. */ + if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) { + backend = e_mail_config_service_page_lookup_backend ( + sending_page, provider->protocol); + gtk_widget_hide (GTK_WIDGET (sending_page)); + } else { + backend = e_mail_config_service_page_lookup_backend ( + sending_page, page_class->default_backend_name); + gtk_widget_show (GTK_WIDGET (sending_page)); + } + + e_mail_config_service_page_set_active_backend (sending_page, backend); + +notify: + g_object_freeze_notify (G_OBJECT (assistant)); + + g_object_notify (G_OBJECT (assistant), "account-backend"); + g_object_notify (G_OBJECT (assistant), "account-source"); + + g_object_thaw_notify (G_OBJECT (assistant)); +} + +static void +mail_config_assistant_notify_transport_backend (EMailConfigServicePage *page, + GParamSpec *pspec, + EMailConfigAssistant *assistant) +{ + g_object_freeze_notify (G_OBJECT (assistant)); + + g_object_notify (G_OBJECT (assistant), "transport-backend"); + g_object_notify (G_OBJECT (assistant), "transport-source"); + + g_object_thaw_notify (G_OBJECT (assistant)); +} + +static void +mail_config_assistant_page_changed (EMailConfigPage *page, + EMailConfigAssistant *assistant) +{ + gtk_assistant_set_page_complete ( + GTK_ASSISTANT (assistant), GTK_WIDGET (page), + e_mail_config_page_check_complete (page)); +} + +static void +mail_config_assistant_autoconfigure_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EMailConfigAssistantPrivate *priv; + GtkAssistant *assistant; + EMailAutoconfig *autoconfig; + const gchar *email_address; + gint n_pages, ii; + GError *error = NULL; + + assistant = GTK_ASSISTANT (user_data); + priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (assistant); + + /* Whether it works or not, we only do this once. */ + priv->auto_configure_done = TRUE; + + autoconfig = e_mail_autoconfig_finish (result, &error); + + /* We don't really care about errors, we only capture the GError + * as a debugging aid. If this doesn't work we simply proceed to + * the Receiving Email page. */ + if (error != NULL) { + gtk_assistant_next_page (assistant); + g_error_free (error); + goto exit; + } + + g_return_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig)); + + /* Autoconfiguration worked! Feed the results to the + * service pages and then skip to the Summary page. */ + + e_mail_config_service_page_auto_configure ( + priv->receiving_page, autoconfig); + + e_mail_config_service_page_auto_configure ( + priv->sending_page, autoconfig); + + /* Also set the initial account name to the email address + * given so the user can just click past the Summary page. */ + email_address = e_mail_autoconfig_get_email_address (autoconfig); + e_mail_config_summary_page_set_account_name ( + priv->summary_page, email_address); + + /* XXX Can't find a better way to learn the page number of + * the summary page. Oh my god this API is horrible. */ + n_pages = gtk_assistant_get_n_pages (assistant); + for (ii = 0; ii < n_pages; ii++) { + GtkWidget *nth_page; + + nth_page = gtk_assistant_get_nth_page (assistant, ii); + if (E_IS_MAIL_CONFIG_SUMMARY_PAGE (nth_page)) + break; + } + + g_warn_if_fail (ii < n_pages); + gtk_assistant_set_current_page (assistant, ii); + +exit: + /* Set the page invisible so we never revisit it. */ + gtk_widget_set_visible (GTK_WIDGET (priv->lookup_page), FALSE); + + g_object_unref (assistant); +} + +static gboolean +mail_config_assistant_provider_page_visible (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer unused) +{ + EMailConfigServiceBackend *active_backend; + EMailConfigServiceBackend *page_backend; + EMailConfigProviderPage *page; + GObject *target_object; + gboolean visible; + + target_object = g_binding_get_target (binding); + page = E_MAIL_CONFIG_PROVIDER_PAGE (target_object); + page_backend = e_mail_config_provider_page_get_backend (page); + + active_backend = g_value_get_object (source_value); + visible = (page_backend == active_backend); + g_value_set_boolean (target_value, visible); + + return TRUE; +} + +static void +mail_config_assistant_close_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + EMailConfigAssistant *assistant; + GdkWindow *gdk_window; + GError *error = NULL; + + assistant = E_MAIL_CONFIG_ASSISTANT (object); + + /* Set the cursor back to normal. */ + gdk_window = gtk_widget_get_window (GTK_WIDGET (assistant)); + gdk_window_set_cursor (gdk_window, NULL); + + /* Allow user interaction with window content. */ + gtk_widget_set_sensitive (GTK_WIDGET (assistant), TRUE); + + e_mail_config_assistant_commit_finish (assistant, result, &error); + + /* Ignore cancellations. */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + + } else if (error != NULL) { + e_alert_submit ( + E_ALERT_SINK (assistant), + "mail:session-message-error", + error->message, NULL); + g_error_free (error); + + } else { + gtk_widget_destroy (GTK_WIDGET (assistant)); + } +} + +static void +mail_config_assistant_set_session (EMailConfigAssistant *assistant, + EMailSession *session) +{ + g_return_if_fail (E_IS_MAIL_SESSION (session)); + g_return_if_fail (assistant->priv->session == NULL); + + assistant->priv->session = g_object_ref (session); +} + +static void +mail_config_assistant_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SESSION: + mail_config_assistant_set_session ( + E_MAIL_CONFIG_ASSISTANT (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_assistant_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_BACKEND: + g_value_set_object ( + value, + e_mail_config_assistant_get_account_backend ( + E_MAIL_CONFIG_ASSISTANT (object))); + return; + + case PROP_ACCOUNT_SOURCE: + g_value_set_object ( + value, + e_mail_config_assistant_get_account_source ( + E_MAIL_CONFIG_ASSISTANT (object))); + return; + + case PROP_IDENTITY_SOURCE: + g_value_set_object ( + value, + e_mail_config_assistant_get_identity_source ( + E_MAIL_CONFIG_ASSISTANT (object))); + return; + + case PROP_SESSION: + g_value_set_object ( + value, + e_mail_config_assistant_get_session ( + E_MAIL_CONFIG_ASSISTANT (object))); + return; + + case PROP_TRANSPORT_BACKEND: + g_value_set_object ( + value, + e_mail_config_assistant_get_transport_backend ( + E_MAIL_CONFIG_ASSISTANT (object))); + return; + + case PROP_TRANSPORT_SOURCE: + g_value_set_object ( + value, + e_mail_config_assistant_get_transport_source ( + E_MAIL_CONFIG_ASSISTANT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_assistant_dispose (GObject *object) +{ + EMailConfigAssistantPrivate *priv; + + priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (object); + + if (priv->session != NULL) { + g_object_unref (priv->session); + priv->session = NULL; + } + + if (priv->identity_source != NULL) { + g_object_unref (priv->identity_source); + priv->identity_source = NULL; + } + + if (priv->receiving_page != NULL) { + g_object_unref (priv->receiving_page); + priv->receiving_page = NULL; + } + + if (priv->sending_page != NULL) { + g_object_unref (priv->sending_page); + priv->sending_page = NULL; + } + + if (priv->summary_page != NULL) { + g_object_unref (priv->summary_page); + priv->summary_page = NULL; + } + + if (priv->lookup_page != NULL) { + g_object_unref (priv->lookup_page); + priv->lookup_page = NULL; + } + + g_ptr_array_set_size (priv->account_sources, 0); + g_ptr_array_set_size (priv->transport_sources, 0); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_assistant_parent_class)-> + dispose (object); +} + +static void +mail_config_assistant_finalize (GObject *object) +{ + EMailConfigAssistantPrivate *priv; + + priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (object); + + g_ptr_array_free (priv->account_sources, TRUE); + g_ptr_array_free (priv->transport_sources, TRUE); + + g_hash_table_destroy (priv->visited_pages); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_assistant_parent_class)-> + finalize (object); +} + +static void +mail_config_assistant_constructed (GObject *object) +{ + EMailConfigAssistant *assistant; + ESource *identity_source; + ESourceRegistry *registry; + ESourceExtension *extension; + ESourceMailComposition *mail_composition_extension; + ESourceMailIdentity *mail_identity_extension; + ESourceMailSubmission *mail_submission_extension; + EMailSession *session; + EMailConfigPage *page; + GList *list, *link; + const gchar *extension_name; + const gchar *title; + + assistant = E_MAIL_CONFIG_ASSISTANT (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_assistant_parent_class)-> + constructed (object); + + title = _("Evolution Account Assistant"); + gtk_window_set_title (GTK_WINDOW (assistant), title); + gtk_window_set_position (GTK_WINDOW (assistant), GTK_WIN_POS_CENTER); + + session = e_mail_config_assistant_get_session (assistant); + registry = e_mail_session_get_registry (session); + + /* Configure a new identity source. */ + + identity_source = e_source_new (NULL, NULL, NULL); + assistant->priv->identity_source = identity_source; + session = e_mail_config_assistant_get_session (assistant); + + extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION; + extension = e_source_get_extension (identity_source, extension_name); + mail_composition_extension = E_SOURCE_MAIL_COMPOSITION (extension); + + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + extension = e_source_get_extension (identity_source, extension_name); + mail_identity_extension = E_SOURCE_MAIL_IDENTITY (extension); + + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + extension = e_source_get_extension (identity_source, extension_name); + mail_submission_extension = E_SOURCE_MAIL_SUBMISSION (extension); + + e_source_mail_composition_set_drafts_folder ( + mail_composition_extension, + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_DRAFTS)); + + e_source_mail_composition_set_templates_folder ( + mail_composition_extension, + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_TEMPLATES)); + + e_source_mail_submission_set_sent_folder ( + mail_submission_extension, + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_SENT)); + + /*** Welcome Page ***/ + + page = e_mail_config_welcome_page_new (); + e_mail_config_assistant_add_page (assistant, page); + + /*** Identity Page ***/ + + page = e_mail_config_identity_page_new (registry, identity_source); + e_mail_config_identity_page_set_show_account_info ( + E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE); + e_mail_config_identity_page_set_show_signatures ( + E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE); + e_mail_config_assistant_add_page (assistant, page); + + /*** Lookup Page ***/ + + page = e_mail_config_lookup_page_new (); + e_mail_config_assistant_add_page (assistant, page); + assistant->priv->lookup_page = g_object_ref (page); + + /*** Receiving Page ***/ + + page = e_mail_config_receiving_page_new (registry); + e_mail_config_assistant_add_page (assistant, page); + assistant->priv->receiving_page = g_object_ref (page); + + g_object_bind_property ( + mail_identity_extension, "address", + page, "email-address", + G_BINDING_SYNC_CREATE); + + g_signal_connect ( + page, "notify::active-backend", + G_CALLBACK (mail_config_assistant_notify_account_backend), + assistant); + + /*** Receiving Options (multiple) ***/ + + /* Populate the Receiving Email page while at the same time + * adding a Receiving Options page for each account type. */ + + list = mail_config_assistant_list_providers (); + + for (link = list; link != NULL; link = g_list_next (link)) { + EMailConfigServiceBackend *backend; + CamelProvider *provider = link->data; + ESourceBackend *backend_extension; + ESource *scratch_source; + const gchar *backend_name; + + if (provider->object_types[CAMEL_PROVIDER_STORE] == 0) + continue; + + /* ESource uses "backend_name" and CamelProvider + * uses "protocol", but the terms are synonymous. */ + backend_name = provider->protocol; + + scratch_source = e_source_new (NULL, NULL, NULL); + backend_extension = e_source_get_extension ( + scratch_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT); + e_source_backend_set_backend_name ( + backend_extension, backend_name); + + /* We always pass NULL for the collection argument. + * The backend generates its own scratch collection + * source if implements the new_collection() method. */ + backend = e_mail_config_service_page_add_scratch_source ( + assistant->priv->receiving_page, scratch_source, NULL); + + g_object_unref (scratch_source); + + page = e_mail_config_provider_page_new (backend); + + /* Note: We exclude this page if it has no options, + * but we don't know that until we create it. */ + if (e_mail_config_provider_page_is_empty ( + E_MAIL_CONFIG_PROVIDER_PAGE (page))) { + g_object_unref (g_object_ref_sink (page)); + continue; + } else { + e_mail_config_assistant_add_page (assistant, page); + } + + /* Each Receiving Options page is only visible when its + * service backend is active on the Receiving Email page. */ + g_object_bind_property_full ( + assistant->priv->receiving_page, "active-backend", + page, "visible", + G_BINDING_SYNC_CREATE, + mail_config_assistant_provider_page_visible, + NULL, + NULL, (GDestroyNotify) NULL); + } + + g_list_free (list); + + /*** Sending Page ***/ + + page = e_mail_config_sending_page_new (registry); + e_mail_config_assistant_add_page (assistant, page); + assistant->priv->sending_page = g_object_ref (page); + + g_object_bind_property ( + mail_identity_extension, "address", + page, "email-address", + G_BINDING_SYNC_CREATE); + + g_signal_connect ( + page, "notify::active-backend", + G_CALLBACK (mail_config_assistant_notify_transport_backend), + assistant); + + list = mail_config_assistant_list_providers (); + + for (link = list; link != NULL; link = g_list_next (link)) { + CamelProvider *provider = link->data; + ESourceBackend *backend_extension; + ESource *scratch_source; + const gchar *backend_name; + + if (provider->object_types[CAMEL_PROVIDER_TRANSPORT] == 0) + continue; + + /* ESource uses "backend_name" and CamelProvider + * uses "protocol", but the terms are synonymous. */ + backend_name = provider->protocol; + + scratch_source = e_source_new (NULL, NULL, NULL); + backend_extension = e_source_get_extension ( + scratch_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT); + e_source_backend_set_backend_name ( + backend_extension, backend_name); + + /* We always pass NULL for the collection argument. + * The backend generates its own scratch collection + * source if implements the new_collection() method. */ + e_mail_config_service_page_add_scratch_source ( + assistant->priv->sending_page, scratch_source, NULL); + + g_object_unref (scratch_source); + } + + g_list_free (list); + + /*** Summary Page ***/ + + page = e_mail_config_summary_page_new (); + e_mail_config_assistant_add_page (assistant, page); + assistant->priv->summary_page = g_object_ref (page); + + g_object_bind_property ( + assistant, "account-backend", + page, "account-backend", + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + assistant, "identity-source", + page, "identity-source", + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + assistant, "transport-backend", + page, "transport-backend", + G_BINDING_SYNC_CREATE); + + /*** Confirm Page ***/ + + page = e_mail_config_confirm_page_new (); + e_mail_config_assistant_add_page (assistant, page); + + e_extensible_load_extensions (E_EXTENSIBLE (assistant)); +} + +static void +mail_config_assistant_remove (GtkContainer *container, + GtkWidget *widget) +{ + if (E_IS_MAIL_CONFIG_PAGE (widget)) + g_signal_handlers_disconnect_by_func ( + widget, mail_config_assistant_page_changed, + E_MAIL_CONFIG_ASSISTANT (container)); + + /* Chain up to parent's remove() method. */ + GTK_CONTAINER_CLASS (e_mail_config_assistant_parent_class)-> + remove (container, widget); +} + +static void +mail_config_assistant_prepare (GtkAssistant *assistant, + GtkWidget *page) +{ + EMailConfigAssistantPrivate *priv; + + priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (assistant); + + /* Only setup defaults the first time a page is visited. */ + if (!g_hash_table_contains (priv->visited_pages, page)) { + if (E_IS_MAIL_CONFIG_PAGE (page)) + e_mail_config_page_setup_defaults ( + E_MAIL_CONFIG_PAGE (page)); + g_hash_table_add (priv->visited_pages, page); + } + + if (E_IS_MAIL_CONFIG_LOOKUP_PAGE (page)) { + ESource *source; + ESourceMailIdentity *extension; + const gchar *email_address; + const gchar *extension_name; + + source = priv->identity_source; + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + extension = e_source_get_extension (source, extension_name); + email_address = e_source_mail_identity_get_address (extension); + + /* XXX This operation is not cancellable. */ + e_mail_autoconfig_new ( + email_address, G_PRIORITY_DEFAULT, NULL, + mail_config_assistant_autoconfigure_cb, + g_object_ref (assistant)); + } +} + +static void +mail_config_assistant_close (GtkAssistant *assistant) +{ + GdkCursor *gdk_cursor; + GdkWindow *gdk_window; + + /* Do not chain up. GtkAssistant does not implement this method. */ + + /* Make the cursor appear busy. */ + gdk_cursor = gdk_cursor_new (GDK_WATCH); + gdk_window = gtk_widget_get_window (GTK_WIDGET (assistant)); + gdk_window_set_cursor (gdk_window, gdk_cursor); + g_object_unref (gdk_cursor); + + /* Prevent user interaction with window content. */ + gtk_widget_set_sensitive (GTK_WIDGET (assistant), FALSE); + + /* XXX This operation is not cancellable. */ + e_mail_config_assistant_commit ( + E_MAIL_CONFIG_ASSISTANT (assistant), + NULL, mail_config_assistant_close_cb, NULL); +} + +static void +mail_config_assistant_cancel (GtkAssistant *assistant) +{ + /* Do not chain up. GtkAssistant does not implement this method. */ + + gtk_widget_destroy (GTK_WIDGET (assistant)); +} + +static void +e_mail_config_assistant_class_init (EMailConfigAssistantClass *class) +{ + GObjectClass *object_class; + GtkContainerClass *container_class; + GtkAssistantClass *assistant_class; + + g_type_class_add_private (class, sizeof (EMailConfigAssistantPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_assistant_set_property; + object_class->get_property = mail_config_assistant_get_property; + object_class->dispose = mail_config_assistant_dispose; + object_class->finalize = mail_config_assistant_finalize; + object_class->constructed = mail_config_assistant_constructed; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->remove = mail_config_assistant_remove; + + assistant_class = GTK_ASSISTANT_CLASS (class); + assistant_class->prepare = mail_config_assistant_prepare; + assistant_class->close = mail_config_assistant_close; + assistant_class->cancel = mail_config_assistant_cancel; + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT_BACKEND, + g_param_spec_object ( + "account-backend", + "Account Backend", + "Active mail account service backend", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT_SOURCE, + g_param_spec_object ( + "account-source", + "Account Source", + "Mail account source being edited", + E_TYPE_SOURCE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_IDENTITY_SOURCE, + g_param_spec_object ( + "identity-source", + "Identity Source", + "Mail identity source being edited", + E_TYPE_SOURCE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SESSION, + g_param_spec_object ( + "session", + "Session", + "Mail session", + E_TYPE_MAIL_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_TRANSPORT_BACKEND, + g_param_spec_object ( + "transport-backend", + "Transport Backend", + "Active mail transport service backend", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_TRANSPORT_SOURCE, + g_param_spec_object ( + "transport-source", + "Transport Source", + "Mail transport source being edited", + E_TYPE_SOURCE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_assistant_init (EMailConfigAssistant *assistant) +{ + assistant->priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (assistant); + + assistant->priv->account_sources = + g_ptr_array_new_with_free_func ( + (GDestroyNotify) g_object_unref); + + assistant->priv->transport_sources = + g_ptr_array_new_with_free_func ( + (GDestroyNotify) g_object_unref); + + assistant->priv->visited_pages = g_hash_table_new (NULL, NULL); +} + +GtkWidget * +e_mail_config_assistant_new (EMailSession *session) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_ASSISTANT, + "session", session, NULL); +} + +EMailSession * +e_mail_config_assistant_get_session (EMailConfigAssistant *assistant) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL); + + return assistant->priv->session; +} + +EMailConfigServiceBackend * +e_mail_config_assistant_get_account_backend (EMailConfigAssistant *assistant) +{ + EMailConfigServicePage *page; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL); + + page = assistant->priv->receiving_page; + + return e_mail_config_service_page_get_active_backend (page); +} + +ESource * +e_mail_config_assistant_get_account_source (EMailConfigAssistant *assistant) +{ + EMailConfigServiceBackend *backend; + ESource *source = NULL; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL); + + backend = e_mail_config_assistant_get_account_backend (assistant); + + if (backend != NULL) + source = e_mail_config_service_backend_get_source (backend); + + return source; +} + +ESource * +e_mail_config_assistant_get_identity_source (EMailConfigAssistant *assistant) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL); + + return assistant->priv->identity_source; +} + +EMailConfigServiceBackend * +e_mail_config_assistant_get_transport_backend (EMailConfigAssistant *assistant) +{ + EMailConfigServicePage *page; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL); + + page = assistant->priv->sending_page; + + return e_mail_config_service_page_get_active_backend (page); +} + +ESource * +e_mail_config_assistant_get_transport_source (EMailConfigAssistant *assistant) +{ + EMailConfigServiceBackend *backend; + ESource *source = NULL; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL); + + backend = e_mail_config_assistant_get_transport_backend (assistant); + + if (backend != NULL) + source = e_mail_config_service_backend_get_source (backend); + + return source; +} + +void +e_mail_config_assistant_add_page (EMailConfigAssistant *assistant, + EMailConfigPage *page) +{ + EMailConfigPageInterface *page_interface; + GtkAssistantPageType page_type; + GtkWidget *page_widget; + gint n_pages, position; + const gchar *page_title; + gboolean complete; + + g_return_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant)); + g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page)); + + page_widget = GTK_WIDGET (page); + page_interface = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page); + page_type = page_interface->page_type; + page_title = page_interface->title; + + /* Determine the position to insert the page. */ + n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT (assistant)); + for (position = 0; position < n_pages; position++) { + GtkWidget *nth_page; + + nth_page = gtk_assistant_get_nth_page ( + GTK_ASSISTANT (assistant), position); + if (e_mail_config_page_compare (page_widget, nth_page) < 0) + break; + } + + gtk_widget_show (page_widget); + + /* Some pages can be clicked through unchanged. */ + complete = e_mail_config_page_check_complete (page); + + gtk_assistant_insert_page ( + GTK_ASSISTANT (assistant), page_widget, position); + gtk_assistant_set_page_type ( + GTK_ASSISTANT (assistant), page_widget, page_type); + gtk_assistant_set_page_title ( + GTK_ASSISTANT (assistant), page_widget, page_title); + gtk_assistant_set_page_complete ( + GTK_ASSISTANT (assistant), page_widget, complete); + + /* XXX GtkAssistant has no equivalent to GtkNotebook's + * "page-added" and "page-removed" signals. Fortunately + * removing a page does trigger GtkContainer::remove, so + * we can override that method and disconnect our signal + * handler before chaining up. But I don't see any way + * for a subclass to intercept GtkAssistant pages being + * added, so we have to connect our signal handler here. + * Not really an issue, I'm just being pedantic. */ + + g_signal_connect ( + page, "changed", + G_CALLBACK (mail_config_assistant_page_changed), + assistant); +} + +/********************* e_mail_config_assistant_commit() **********************/ + +static void +mail_config_assistant_commit_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + simple = G_SIMPLE_ASYNC_RESULT (user_data); + + e_source_registry_create_sources_finish ( + E_SOURCE_REGISTRY (object), result, &error); + + if (error != NULL) + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + + g_object_unref (simple); +} + +void +e_mail_config_assistant_commit (EMailConfigAssistant *assistant, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EMailConfigServiceBackend *backend; + GSimpleAsyncResult *simple; + ESourceRegistry *registry; + EMailSession *session; + ESource *source; + GQueue *queue; + gint n_pages, ii; + + g_return_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant)); + + session = e_mail_config_assistant_get_session (assistant); + registry = e_mail_session_get_registry (session); + + queue = g_queue_new (); + + /* Queue the collection data source if one is defined. */ + backend = e_mail_config_assistant_get_account_backend (assistant); + source = e_mail_config_service_backend_get_collection (backend); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + + /* Queue the mail-related data sources for the account. */ + source = e_mail_config_assistant_get_account_source (assistant); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + source = e_mail_config_assistant_get_identity_source (assistant); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + source = e_mail_config_assistant_get_transport_source (assistant); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + + n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT (assistant)); + + /* Tell all EMailConfigPages to commit their UI state to their + * scratch ESources and push any additional data sources on to + * the given source queue, such as calendars or address books + * to be bundled with the mail account. */ + for (ii = 0; ii < n_pages; ii++) { + GtkWidget *widget; + + widget = gtk_assistant_get_nth_page ( + GTK_ASSISTANT (assistant), ii); + + if (E_IS_MAIL_CONFIG_PAGE (widget)) { + EMailConfigPage *page; + page = E_MAIL_CONFIG_PAGE (widget); + e_mail_config_page_commit_changes (page, queue); + } + } + + simple = g_simple_async_result_new ( + G_OBJECT (assistant), callback, user_data, + e_mail_config_assistant_commit); + + e_source_registry_create_sources ( + registry, g_queue_peek_head_link (queue), + cancellable, mail_config_assistant_commit_cb, simple); + + g_queue_free_full (queue, (GDestroyNotify) g_object_unref); +} + +gboolean +e_mail_config_assistant_commit_finish (EMailConfigAssistant *assistant, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail ( + g_simple_async_result_is_valid ( + result, G_OBJECT (assistant), + e_mail_config_assistant_commit), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + /* Assume success unless a GError is set. */ + return !g_simple_async_result_propagate_error (simple, error); +} + diff --git a/mail/e-mail-config-assistant.h b/mail/e-mail-config-assistant.h new file mode 100644 index 0000000000..de225af921 --- /dev/null +++ b/mail/e-mail-config-assistant.h @@ -0,0 +1,96 @@ +/* + * e-mail-config-assistant.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_CONFIG_ASSISTANT_H +#define E_MAIL_CONFIG_ASSISTANT_H + +#include <gtk/gtk.h> + +#include <mail/e-mail-config-page.h> +#include <mail/e-mail-config-service-backend.h> +#include <libemail-engine/e-mail-session.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_ASSISTANT \ + (e_mail_config_assistant_get_type ()) +#define E_MAIL_CONFIG_ASSISTANT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistant)) +#define E_MAIL_CONFIG_ASSISTANT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistantClass)) +#define E_IS_MAIL_CONFIG_ASSISTANT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_ASSISTANT)) +#define E_IS_MAIL_CONFIG_ASSISTANT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_ASSISTANT)) +#define E_MAIL_CONFIG_ASSISTANT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistantClass)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigAssistant EMailConfigAssistant; +typedef struct _EMailConfigAssistantClass EMailConfigAssistantClass; +typedef struct _EMailConfigAssistantPrivate EMailConfigAssistantPrivate; + +struct _EMailConfigAssistant { + GtkAssistant parent; + EMailConfigAssistantPrivate *priv; +}; + +struct _EMailConfigAssistantClass { + GtkAssistantClass parent_class; +}; + +GType e_mail_config_assistant_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_config_assistant_new + (EMailSession *session); +EMailSession * e_mail_config_assistant_get_session + (EMailConfigAssistant *assistant); +EMailConfigServiceBackend * + e_mail_config_assistant_get_account_backend + (EMailConfigAssistant *assistant); +ESource * e_mail_config_assistant_get_account_source + (EMailConfigAssistant *assistant); +ESource * e_mail_config_assistant_get_identity_source + (EMailConfigAssistant *assistant); +EMailConfigServiceBackend * + e_mail_config_assistant_get_transport_backend + (EMailConfigAssistant *assistant); +ESource * e_mail_config_assistant_get_transport_source + (EMailConfigAssistant *assistant); +void e_mail_config_assistant_add_page + (EMailConfigAssistant *assistant, + EMailConfigPage *page); +void e_mail_config_assistant_commit + (EMailConfigAssistant *assistant, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean e_mail_config_assistant_commit_finish + (EMailConfigAssistant *assistant, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_ASSISTANT_H */ + diff --git a/mail/e-mail-config-auth-check.c b/mail/e-mail-config-auth-check.c new file mode 100644 index 0000000000..22523e5af0 --- /dev/null +++ b/mail/e-mail-config-auth-check.c @@ -0,0 +1,446 @@ +/* + * e-mail-config-auth-check.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-config-auth-check.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libevolution-utils/e-alert.h> +#include <e-util/e-mktemp.h> +#include <misc/e-auth-combo-box.h> +#include <mail/e-mail-config-service-page.h> + +#define E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheckPrivate)) + +typedef struct _AsyncContext AsyncContext; + +struct _EMailConfigAuthCheckPrivate { + EMailConfigServiceBackend *backend; + gchar *active_mechanism; + + GtkWidget *combo_box; /* not referenced */ +}; + +struct _AsyncContext { + EMailConfigAuthCheck *auth_check; + CamelSession *temporary_session; + EActivity *activity; +}; + +enum { + PROP_0, + PROP_ACTIVE_MECHANISM, + PROP_BACKEND +}; + +G_DEFINE_TYPE ( + EMailConfigAuthCheck, + e_mail_config_auth_check, + GTK_TYPE_BOX) + +static void +async_context_free (AsyncContext *async_context) +{ + if (async_context->auth_check != NULL) + g_object_unref (async_context->auth_check); + + if (async_context->temporary_session != NULL) + g_object_unref (async_context->temporary_session); + + if (async_context->activity != NULL) + g_object_unref (async_context->activity); + + g_slice_free (AsyncContext, async_context); +} + +static void +mail_config_auth_check_update_done_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + AsyncContext *async_context = user_data; + EMailConfigAuthCheck *auth_check; + EAlertSink *alert_sink; + GList *available_authtypes; + GError *error = NULL; + + auth_check = async_context->auth_check; + alert_sink = e_activity_get_alert_sink (async_context->activity); + + available_authtypes = camel_service_query_auth_types_finish ( + CAMEL_SERVICE (source_object), result, &error); + + if (e_activity_handle_cancellation (async_context->activity, error)) { + g_warn_if_fail (available_authtypes == NULL); + g_error_free (error); + + } else if (error != NULL) { + g_warn_if_fail (available_authtypes == NULL); + e_alert_submit ( + alert_sink, + "mail:checking-service-error", + error->message, NULL); + g_error_free (error); + + } else { + e_auth_combo_box_update_available ( + E_AUTH_COMBO_BOX (auth_check->priv->combo_box), + available_authtypes); + g_list_free (available_authtypes); + } + + gtk_widget_set_sensitive (GTK_WIDGET (auth_check), TRUE); + + async_context_free (async_context); +} + +static void +mail_config_auth_check_update (EMailConfigAuthCheck *auth_check) +{ + EActivity *activity; + EMailConfigServicePage *page; + EMailConfigServiceBackend *backend; + EMailConfigServicePageClass *page_class; + EMailConfigServiceBackendClass *backend_class; + CamelService *service; + CamelSession *session; + CamelSettings *settings; + GCancellable *cancellable; + AsyncContext *async_context; + gchar *temp_dir; + GError *error = NULL; + + backend = e_mail_config_auth_check_get_backend (auth_check); + page = e_mail_config_service_backend_get_page (backend); + settings = e_mail_config_service_backend_get_settings (backend); + + page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page); + backend_class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + + temp_dir = e_mkdtemp ("evolution-auth-check-XXXXXX"); + + /* Create a temporary session for our temporary service. + * Use the same temporary directory for "user-data-dir" and + * "user-cache-dir". For our purposes it shouldn't matter. */ + session = g_object_new ( + CAMEL_TYPE_SESSION, + "user-data-dir", temp_dir, + "user-cache-dir", temp_dir, + NULL); + + /* This returns a BORROWED reference to the CamelService. */ + service = camel_session_add_service ( + session, "fake-uid", + backend_class->backend_name, + page_class->provider_type, &error); + + g_free (temp_dir); + + if (error != NULL) { + g_warn_if_fail (service == NULL); + e_alert_submit ( + E_ALERT_SINK (page), + "mail:checking-service-error", + error->message, NULL); + g_error_free (error); + return; + } + + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + camel_service_set_settings (service, settings); + + activity = e_mail_config_service_page_new_activity (page); + cancellable = e_activity_get_cancellable (activity); + + gtk_widget_set_sensitive (GTK_WIDGET (auth_check), FALSE); + + async_context = g_slice_new (AsyncContext); + async_context->auth_check = g_object_ref (auth_check); + async_context->temporary_session = session; /* takes ownership */ + async_context->activity = activity; /* takes ownership */ + + camel_service_query_auth_types ( + service, G_PRIORITY_DEFAULT, cancellable, + mail_config_auth_check_update_done_cb, async_context); +} + +static void +mail_config_auth_check_clicked_cb (GtkButton *button, + EMailConfigAuthCheck *auth_check) +{ + mail_config_auth_check_update (auth_check); +} + +static void +mail_config_auth_check_init_mechanism (EMailConfigAuthCheck *auth_check) +{ + EMailConfigServiceBackend *backend; + CamelProvider *provider; + CamelSettings *settings; + const gchar *auth_mechanism = NULL; + + /* Pick an initial active mechanism name by examining both + * the corresponding CamelNetworkSettings and CamelProvider. */ + + backend = e_mail_config_auth_check_get_backend (auth_check); + provider = e_mail_config_service_backend_get_provider (backend); + settings = e_mail_config_service_backend_get_settings (backend); + g_return_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings)); + + auth_mechanism = + camel_network_settings_get_auth_mechanism ( + CAMEL_NETWORK_SETTINGS (settings)); + + /* If CamelNetworkSettings does not have a mechanism name set, + * choose from the CamelProvider's list of supported mechanisms. */ + if (auth_mechanism == NULL && provider != NULL) { + if (provider->authtypes != NULL) { + CamelServiceAuthType *auth_type; + auth_type = provider->authtypes->data; + auth_mechanism = auth_type->authproto; + } + } + + if (auth_mechanism != NULL) + e_mail_config_auth_check_set_active_mechanism ( + auth_check, auth_mechanism); +} + +static void +mail_config_auth_check_set_backend (EMailConfigAuthCheck *auth_check, + EMailConfigServiceBackend *backend) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + g_return_if_fail (auth_check->priv->backend == NULL); + + auth_check->priv->backend = g_object_ref (backend); +} + +static void +mail_config_auth_check_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE_MECHANISM: + e_mail_config_auth_check_set_active_mechanism ( + E_MAIL_CONFIG_AUTH_CHECK (object), + g_value_get_string (value)); + return; + + case PROP_BACKEND: + mail_config_auth_check_set_backend ( + E_MAIL_CONFIG_AUTH_CHECK (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_auth_check_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE_MECHANISM: + g_value_set_string ( + value, + e_mail_config_auth_check_get_active_mechanism ( + E_MAIL_CONFIG_AUTH_CHECK (object))); + return; + + case PROP_BACKEND: + g_value_set_object ( + value, + e_mail_config_auth_check_get_backend ( + E_MAIL_CONFIG_AUTH_CHECK (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_auth_check_dispose (GObject *object) +{ + EMailConfigAuthCheckPrivate *priv; + + priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (object); + + if (priv->backend != NULL) { + g_object_unref (priv->backend); + priv->backend = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)-> + dispose (object); +} + +static void +mail_config_auth_check_finalize (GObject *object) +{ + EMailConfigAuthCheckPrivate *priv; + + priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (object); + + g_free (priv->active_mechanism); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)-> + finalize (object); +} + +static void +mail_config_auth_check_constructed (GObject *object) +{ + EMailConfigAuthCheck *auth_check; + EMailConfigServiceBackend *backend; + CamelProvider *provider; + GtkWidget *widget; + const gchar *text; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)-> + constructed (object); + + auth_check = E_MAIL_CONFIG_AUTH_CHECK (object); + backend = e_mail_config_auth_check_get_backend (auth_check); + provider = e_mail_config_service_backend_get_provider (backend); + + widget = e_auth_combo_box_new (); + e_auth_combo_box_set_provider (E_AUTH_COMBO_BOX (widget), provider); + gtk_box_pack_start (GTK_BOX (object), widget, FALSE, FALSE, 0); + auth_check->priv->combo_box = widget; /* do not reference */ + gtk_widget_show (widget); + + g_object_bind_property ( + widget, "active-id", + auth_check, "active-mechanism", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + text = _("Check for Supported Types"); + widget = gtk_button_new_with_label (text); + gtk_box_pack_start (GTK_BOX (object), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_signal_connect ( + widget, "clicked", + G_CALLBACK (mail_config_auth_check_clicked_cb), + auth_check); + + mail_config_auth_check_init_mechanism (auth_check); +} + +static void +e_mail_config_auth_check_class_init (EMailConfigAuthCheckClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailConfigAuthCheckPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_auth_check_set_property; + object_class->get_property = mail_config_auth_check_get_property; + object_class->dispose = mail_config_auth_check_dispose; + object_class->finalize = mail_config_auth_check_finalize; + object_class->constructed = mail_config_auth_check_constructed; + + g_object_class_install_property ( + object_class, + PROP_ACTIVE_MECHANISM, + g_param_spec_string ( + "active-mechanism", + "Active Mechanism", + "Active authentication mechanism", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_BACKEND, + g_param_spec_object ( + "backend", + "Backend", + "Mail configuration backend", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_auth_check_init (EMailConfigAuthCheck *auth_check) +{ + auth_check->priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (auth_check); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (auth_check), + GTK_ORIENTATION_HORIZONTAL); + + gtk_box_set_spacing (GTK_BOX (auth_check), 6); +} + +GtkWidget * +e_mail_config_auth_check_new (EMailConfigServiceBackend *backend) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_AUTH_CHECK, + "backend", backend, NULL); +} + +EMailConfigServiceBackend * +e_mail_config_auth_check_get_backend (EMailConfigAuthCheck *auth_check) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check), NULL); + + return auth_check->priv->backend; +} + +const gchar * +e_mail_config_auth_check_get_active_mechanism (EMailConfigAuthCheck *auth_check) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check), NULL); + + return auth_check->priv->active_mechanism; +} + +void +e_mail_config_auth_check_set_active_mechanism (EMailConfigAuthCheck *auth_check, + const gchar *active_mechanism) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check)); + + g_free (auth_check->priv->active_mechanism); + auth_check->priv->active_mechanism = g_strdup (active_mechanism); + + g_object_notify (G_OBJECT (auth_check), "active-mechanism"); +} + diff --git a/mail/e-mail-config-auth-check.h b/mail/e-mail-config-auth-check.h new file mode 100644 index 0000000000..c7bf759059 --- /dev/null +++ b/mail/e-mail-config-auth-check.h @@ -0,0 +1,73 @@ +/* + * e-mail-config-auth-check.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_CONFIG_AUTH_CHECK_H +#define E_MAIL_CONFIG_AUTH_CHECK_H + +#include <mail/e-mail-config-service-backend.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_AUTH_CHECK \ + (e_mail_config_auth_check_get_type ()) +#define E_MAIL_CONFIG_AUTH_CHECK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheck)) +#define E_MAIL_CONFIG_AUTH_CHECK_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheckClass)) +#define E_IS_MAIL_CONFIG_AUTH_CHECK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK)) +#define E_IS_MAIL_CONFIG_AUTH_CHECK_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_AUTH_CHECK)) +#define E_MAIL_CONFIG_AUTH_CHECK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheckClass)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigAuthCheck EMailConfigAuthCheck; +typedef struct _EMailConfigAuthCheckClass EMailConfigAuthCheckClass; +typedef struct _EMailConfigAuthCheckPrivate EMailConfigAuthCheckPrivate; + +struct _EMailConfigAuthCheck { + GtkBox parent; + EMailConfigAuthCheckPrivate *priv; +}; + +struct _EMailConfigAuthCheckClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_auth_check_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_config_auth_check_new + (EMailConfigServiceBackend *backend); +EMailConfigServiceBackend * + e_mail_config_auth_check_get_backend + (EMailConfigAuthCheck *auth_check); +const gchar * e_mail_config_auth_check_get_active_mechanism + (EMailConfigAuthCheck *auth_check); +void e_mail_config_auth_check_set_active_mechanism + (EMailConfigAuthCheck *auth_check, + const gchar *active_mechanism); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_AUTH_CHECK_H */ diff --git a/mail/e-mail-config-confirm-page.c b/mail/e-mail-config-confirm-page.c new file mode 100644 index 0000000000..f58da035b6 --- /dev/null +++ b/mail/e-mail-config-confirm-page.c @@ -0,0 +1,205 @@ +/* + * e-mail-config-confirm-page.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/> + * + */ + +#include "e-mail-config-confirm-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> + +#define E_MAIL_CONFIG_CONFIRM_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPagePrivate)) + +struct _EMailConfigConfirmPagePrivate { + gchar *text; +}; + +enum { + PROP_0, + PROP_TEXT +}; + +/* Forward Declarations */ +static void e_mail_config_confirm_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigConfirmPage, + e_mail_config_confirm_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_confirm_page_interface_init)) + +static void +mail_config_confirm_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT: + e_mail_config_confirm_page_set_text ( + E_MAIL_CONFIG_CONFIRM_PAGE (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_confirm_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT: + g_value_set_string ( + value, + e_mail_config_confirm_page_get_text ( + E_MAIL_CONFIG_CONFIRM_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_confirm_page_finalize (GObject *object) +{ + EMailConfigConfirmPagePrivate *priv; + + priv = E_MAIL_CONFIG_CONFIRM_PAGE_GET_PRIVATE (object); + + g_free (priv->text); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_confirm_page_parent_class)-> + finalize (object); +} + +static void +mail_config_confirm_page_constructed (GObject *object) +{ + EMailConfigConfirmPage *page; + GtkWidget *widget; + + page = E_MAIL_CONFIG_CONFIRM_PAGE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_confirm_page_parent_class)-> + constructed (object); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + gtk_box_set_spacing (GTK_BOX (page), 12); + + gtk_widget_set_valign (GTK_WIDGET (page), GTK_ALIGN_CENTER); + + widget = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_object_bind_property ( + page, "text", + widget, "label", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_extensible_load_extensions (E_EXTENSIBLE (page)); +} + +static void +e_mail_config_confirm_page_class_init (EMailConfigConfirmPageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigConfirmPagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_confirm_page_set_property; + object_class->get_property = mail_config_confirm_page_get_property; + object_class->finalize = mail_config_confirm_page_finalize; + object_class->constructed = mail_config_confirm_page_constructed; + + g_object_class_install_property ( + object_class, + PROP_TEXT, + g_param_spec_string ( + "text", + "Text", + "Confirmation message", + _("Congratulations, your mail configuration is " + "complete.\n\nYou are now ready to send and " + "receive email using Evolution.\n\nClick " + "\"Apply\" to save your settings."), + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_confirm_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Done"); + interface->page_type = GTK_ASSISTANT_PAGE_CONFIRM; + interface->sort_order = E_MAIL_CONFIG_CONFIRM_PAGE_SORT_ORDER; +} + +static void +e_mail_config_confirm_page_init (EMailConfigConfirmPage *page) +{ + page->priv = E_MAIL_CONFIG_CONFIRM_PAGE_GET_PRIVATE (page); +} + +EMailConfigPage * +e_mail_config_confirm_page_new (void) +{ + return g_object_new (E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, NULL); +} + +const gchar * +e_mail_config_confirm_page_get_text (EMailConfigConfirmPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_CONFIRM_PAGE (page), NULL); + + return page->priv->text; +} + +void +e_mail_config_confirm_page_set_text (EMailConfigConfirmPage *page, + const gchar *text) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_CONFIRM_PAGE (page)); + + g_free (page->priv->text); + page->priv->text = g_strdup ((text != NULL) ? text : ""); + + g_object_notify (G_OBJECT (page), "text"); +} + diff --git a/mail/e-mail-config-confirm-page.h b/mail/e-mail-config-confirm-page.h new file mode 100644 index 0000000000..d4bae9485f --- /dev/null +++ b/mail/e-mail-config-confirm-page.h @@ -0,0 +1,75 @@ +/* + * e-mail-config-confirm-page.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_CONFIG_CONFIRM_PAGE_H +#define E_MAIL_CONFIG_CONFIRM_PAGE_H + +#include <gtk/gtk.h> + +#include <mail/e-mail-config-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_CONFIRM_PAGE \ + (e_mail_config_confirm_page_get_type ()) +#define E_MAIL_CONFIG_CONFIRM_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPage)) +#define E_MAIL_CONFIG_CONFIRM_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPageClass)) +#define E_IS_MAIL_CONFIG_CONFIRM_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE)) +#define E_IS_MAIL_CONFIG_CONFIRM_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE)) +#define E_MAIL_CONFIG_CONFIRM_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPageClass)) + +#define E_MAIL_CONFIG_CONFIRM_PAGE_SORT_ORDER (600) + +G_BEGIN_DECLS + +typedef struct _EMailConfigConfirmPage EMailConfigConfirmPage; +typedef struct _EMailConfigConfirmPageClass EMailConfigConfirmPageClass; +typedef struct _EMailConfigConfirmPagePrivate EMailConfigConfirmPagePrivate; + +struct _EMailConfigConfirmPage { + GtkBox parent; + EMailConfigConfirmPagePrivate *priv; +}; + +struct _EMailConfigConfirmPageClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_confirm_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_confirm_page_new (void); +const gchar * e_mail_config_confirm_page_get_text + (EMailConfigConfirmPage *page); +void e_mail_config_confirm_page_set_text + (EMailConfigConfirmPage *page, + const gchar *text); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_CONFIRM_PAGE_H */ + diff --git a/mail/e-mail-config-defaults-page.c b/mail/e-mail-config-defaults-page.c new file mode 100644 index 0000000000..d815f0560c --- /dev/null +++ b/mail/e-mail-config-defaults-page.c @@ -0,0 +1,868 @@ +/* + * e-mail-config-defaults-page.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-config-defaults-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> +#include <libedataserver/e-source-camel.h> +#include <libedataserver/e-source-enumtypes.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-composition.h> +#include <libedataserver/e-source-mail-submission.h> +#include <libedataserver/e-source-mdn.h> +#include <libedataserver/e-data-server-util.h> + +#include <libemail-engine/e-mail-folder-utils.h> + +#include <mail/e-mail-config-page.h> +#include <mail/em-folder-selection-button.h> + +#define E_MAIL_CONFIG_DEFAULTS_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPagePrivate)) + +struct _EMailConfigDefaultsPagePrivate { + EMailSession *session; + ESource *account_source; + ESource *identity_source; + + GtkWidget *drafts_button; /* not referenced */ + GtkWidget *sent_button; /* not referenced */ + GtkWidget *trash_toggle; /* not referenced */ + GtkWidget *junk_toggle; /* not referenced */ +}; + +enum { + PROP_0, + PROP_ACCOUNT_SOURCE, + PROP_IDENTITY_SOURCE, + PROP_SESSION +}; + +/* Forward Declarations */ +static void e_mail_config_defaults_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigDefaultsPage, + e_mail_config_defaults_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_defaults_page_interface_init)) + +static CamelSettings * +mail_config_defaults_page_maybe_get_settings (EMailConfigDefaultsPage *page) +{ + ESource *source; + ESourceCamel *camel_ext; + ESourceBackend *backend_ext; + const gchar *backend_name; + const gchar *extension_name; + + source = e_mail_config_defaults_page_get_account_source (page); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + backend_ext = e_source_get_extension (source, extension_name); + backend_name = e_source_backend_get_backend_name (backend_ext); + extension_name = e_source_camel_get_extension_name (backend_name); + + /* Avoid accidentally creating a backend-specific extension + * in the mail account source if the mail account source is + * part of a collection, in which case the backend-specific + * extension is kept in the top-level collection source. */ + if (!e_source_has_extension (source, extension_name)) + return NULL; + + camel_ext = e_source_get_extension (source, extension_name); + + return e_source_camel_get_settings (camel_ext); +} + +static CamelStore * +mail_config_defaults_page_get_store (EMailConfigDefaultsPage *page) +{ + ESource *source; + EMailSession *session; + CamelService *service; + const gchar *uid; + + session = e_mail_config_defaults_page_get_session (page); + source = e_mail_config_defaults_page_get_account_source (page); + + uid = e_source_get_uid (source); + service = camel_session_get_service (CAMEL_SESSION (session), uid); + + return CAMEL_IS_STORE (service) ? CAMEL_STORE (service) : NULL; +} + +static gboolean +mail_config_defaults_page_addrs_to_string (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer unused) +{ + gchar **strv; + + strv = g_value_dup_boxed (source_value); + + if (strv != NULL) { + gchar *string = g_strjoinv ("; ", strv); + g_value_set_string (target_value, string); + g_free (string); + } else { + g_value_set_string (target_value, ""); + } + + g_strfreev (strv); + + return TRUE; +} + +static gboolean +mail_config_defaults_page_string_to_addrs (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer unused) +{ + CamelInternetAddress *address; + const gchar *string; + gchar **strv; + gint n_addresses, ii; + + string = g_value_get_string (source_value); + + address = camel_internet_address_new (); + n_addresses = camel_address_decode (CAMEL_ADDRESS (address), string); + + if (n_addresses < 0) { + g_object_unref (address); + return FALSE; + + } else if (n_addresses == 0) { + g_value_set_boxed (target_value, NULL); + g_object_unref (address); + return TRUE; + } + + strv = g_new0 (gchar *, n_addresses + 1); + + for (ii = 0; ii < n_addresses; ii++) { + const gchar *name = NULL; + const gchar *addr = NULL; + + camel_internet_address_get (address, ii, &name, &addr); + strv[ii] = camel_internet_address_format_address (name, addr); + } + + g_value_take_boxed (target_value, strv); + + return TRUE; +} + +static gboolean +mail_config_defaults_page_folder_name_to_uri (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer data) +{ + EMailConfigDefaultsPage *page; + CamelStore *store; + const gchar *folder_name; + gchar *folder_uri = NULL; + + page = E_MAIL_CONFIG_DEFAULTS_PAGE (data); + store = mail_config_defaults_page_get_store (page); + g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); + + folder_name = g_value_get_string (source_value); + + if (folder_name != NULL) + folder_uri = e_mail_folder_uri_build (store, folder_name); + + g_value_set_string (target_value, folder_uri); + + g_free (folder_uri); + + return TRUE; +} + +static gboolean +mail_config_defaults_page_folder_uri_to_name (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer data) +{ + EMailConfigDefaultsPage *page; + EMailSession *session; + const gchar *folder_uri; + gchar *folder_name = NULL; + GError *error = NULL; + + page = E_MAIL_CONFIG_DEFAULTS_PAGE (data); + session = e_mail_config_defaults_page_get_session (page); + + folder_uri = g_value_get_string (source_value); + + if (folder_uri == NULL) { + g_value_set_string (target_value, NULL); + return TRUE; + } + + e_mail_folder_uri_parse ( + CAMEL_SESSION (session), folder_uri, + NULL, &folder_name, &error); + + if (error != NULL) { + g_warn_if_fail (folder_name == NULL); + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + return FALSE; + } + + g_return_val_if_fail (folder_name != NULL, FALSE); + + g_value_set_string (target_value, folder_name); + + g_free (folder_name); + + return TRUE; +} + +static void +mail_config_defaults_page_restore_folders (EMailConfigDefaultsPage *page) +{ + EMFolderSelectionButton *button; + EMailSession *session; + EMailLocalFolder type; + const gchar *folder_uri; + + session = e_mail_config_defaults_page_get_session (page); + + type = E_MAIL_LOCAL_FOLDER_DRAFTS; + button = EM_FOLDER_SELECTION_BUTTON (page->priv->drafts_button); + folder_uri = e_mail_session_get_local_folder_uri (session, type); + em_folder_selection_button_set_folder_uri (button, folder_uri); + + type = E_MAIL_LOCAL_FOLDER_SENT; + button = EM_FOLDER_SELECTION_BUTTON (page->priv->sent_button); + folder_uri = e_mail_session_get_local_folder_uri (session, type); + em_folder_selection_button_set_folder_uri (button, folder_uri); +} + +static void +mail_config_defaults_page_restore_real_folder (GtkToggleButton *toggle_button) +{ + gtk_toggle_button_set_active (toggle_button, FALSE); +} + +static GtkWidget * +mail_config_defaults_page_add_real_folder (EMailConfigDefaultsPage *page, + GtkSizeGroup *size_group, + GtkButton *revert_button, + const gchar *toggle_label, + const gchar *dialog_caption, + const gchar *property_name, + const gchar *use_property_name) +{ + GtkWidget *box; + GtkWidget *check_button; + GtkWidget *folder_button; + EMailSession *session; + CamelSettings *settings; + CamelStore *store; + GObjectClass *class; + + store = mail_config_defaults_page_get_store (page); + g_return_val_if_fail (CAMEL_IS_STORE (store), NULL); + + session = e_mail_config_defaults_page_get_session (page); + settings = mail_config_defaults_page_maybe_get_settings (page); + + if (settings == NULL) + return NULL; + + /* These folder settings are backend-specific, so check if + * the CamelSettings class has the property names we need. */ + + class = G_OBJECT_GET_CLASS (settings); + + if (g_object_class_find_property (class, property_name) == NULL) + return NULL; + + if (g_object_class_find_property (class, use_property_name) == NULL) + return NULL; + + /* We're good to go. */ + + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + + check_button = gtk_check_button_new_with_mnemonic (toggle_label); + g_object_set (check_button, "xalign", 1.0, NULL); + gtk_size_group_add_widget (size_group, check_button); + gtk_box_pack_start (GTK_BOX (box), check_button, FALSE, FALSE, 0); + gtk_widget_show (check_button); + + g_object_bind_property ( + settings, use_property_name, + check_button, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + folder_button = em_folder_selection_button_new ( + session, "", dialog_caption); + em_folder_selection_button_set_store ( + EM_FOLDER_SELECTION_BUTTON (folder_button), store); + gtk_box_pack_start (GTK_BOX (box), folder_button, TRUE, TRUE, 0); + gtk_widget_show (folder_button); + + /* XXX CamelSettings only stores the folder's path name, but the + * EMFolderSelectionButton requires a full folder URI, so we + * have to do some fancy transforms for the binding to work. */ + g_object_bind_property_full ( + settings, property_name, + folder_button, "folder-uri", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + mail_config_defaults_page_folder_name_to_uri, + mail_config_defaults_page_folder_uri_to_name, + g_object_ref (page), + (GDestroyNotify) g_object_unref); + + g_object_bind_property ( + check_button, "active", + folder_button, "sensitive", + G_BINDING_SYNC_CREATE); + + g_signal_connect_swapped ( + revert_button, "clicked", + G_CALLBACK (mail_config_defaults_page_restore_real_folder), + check_button); + + return box; +} + +static void +mail_config_defaults_page_set_account_source (EMailConfigDefaultsPage *page, + ESource *account_source) +{ + g_return_if_fail (E_IS_SOURCE (account_source)); + g_return_if_fail (page->priv->account_source == NULL); + + page->priv->account_source = g_object_ref (account_source); +} + +static void +mail_config_defaults_page_set_identity_source (EMailConfigDefaultsPage *page, + ESource *identity_source) +{ + g_return_if_fail (E_IS_SOURCE (identity_source)); + g_return_if_fail (page->priv->identity_source == NULL); + + page->priv->identity_source = g_object_ref (identity_source); +} + +static void +mail_config_defaults_page_set_session (EMailConfigDefaultsPage *page, + EMailSession *session) +{ + g_return_if_fail (E_IS_MAIL_SESSION (session)); + g_return_if_fail (page->priv->session == NULL); + + page->priv->session = g_object_ref (session); +} + +static void +mail_config_defaults_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_SOURCE: + mail_config_defaults_page_set_account_source ( + E_MAIL_CONFIG_DEFAULTS_PAGE (object), + g_value_get_object (value)); + return; + + case PROP_IDENTITY_SOURCE: + mail_config_defaults_page_set_identity_source ( + E_MAIL_CONFIG_DEFAULTS_PAGE (object), + g_value_get_object (value)); + return; + + case PROP_SESSION: + mail_config_defaults_page_set_session ( + E_MAIL_CONFIG_DEFAULTS_PAGE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_defaults_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_SOURCE: + g_value_set_object ( + value, + e_mail_config_defaults_page_get_account_source ( + E_MAIL_CONFIG_DEFAULTS_PAGE (object))); + return; + + case PROP_IDENTITY_SOURCE: + g_value_set_object ( + value, + e_mail_config_defaults_page_get_identity_source ( + E_MAIL_CONFIG_DEFAULTS_PAGE (object))); + return; + + case PROP_SESSION: + g_value_set_object ( + value, + e_mail_config_defaults_page_get_session ( + E_MAIL_CONFIG_DEFAULTS_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_defaults_page_dispose (GObject *object) +{ + EMailConfigDefaultsPagePrivate *priv; + + priv = E_MAIL_CONFIG_DEFAULTS_PAGE_GET_PRIVATE (object); + + if (priv->identity_source != NULL) { + g_object_unref (priv->identity_source); + priv->identity_source = NULL; + } + + if (priv->session != NULL) { + g_object_unref (priv->session); + priv->session = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_defaults_page_parent_class)-> + dispose (object); +} + +static void +mail_config_defaults_page_constructed (GObject *object) +{ + EMailConfigDefaultsPage *page; + EMailSession *session; + ESource *source; + ESourceMailComposition *composition_ext; + ESourceMailSubmission *submission_ext; + ESourceMDN *mdn_ext; + GtkLabel *label; + GtkButton *button; + GtkWidget *widget; + GtkWidget *container; + GtkSizeGroup *size_group; + GEnumClass *enum_class; + GEnumValue *enum_value; + EMdnResponsePolicy policy; + const gchar *extension_name; + const gchar *text; + gchar *markup; + + page = E_MAIL_CONFIG_DEFAULTS_PAGE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_defaults_page_parent_class)-> + constructed (object); + + session = e_mail_config_defaults_page_get_session (page); + source = e_mail_config_defaults_page_get_identity_source (page); + + extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION; + composition_ext = e_source_get_extension (source, extension_name); + + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + submission_ext = e_source_get_extension (source, extension_name); + + extension_name = E_SOURCE_EXTENSION_MDN; + mdn_ext = e_source_get_extension (source, extension_name); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + gtk_box_set_spacing (GTK_BOX (page), 12); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + /*** Special Folders ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Special Folders"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Draft Messages _Folder:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + text = _("Choose a folder for saving draft messages."); + widget = em_folder_selection_button_new (session, "", text); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1); + page->priv->drafts_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_object_bind_property ( + composition_ext, "drafts-folder", + widget, "folder-uri", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + text = _("Sent _Messages Folder:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + text = _("Choose a folder for saving sent messages."); + widget = em_folder_selection_button_new (session, "", text); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1); + page->priv->sent_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_object_bind_property ( + submission_ext, "sent-folder", + widget, "folder-uri", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + widget = gtk_button_new_with_mnemonic (_("_Restore Defaults")); + gtk_widget_set_halign (widget, GTK_ALIGN_START); + gtk_grid_attach (GTK_GRID (container), widget, 1, 5, 1, 1); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (mail_config_defaults_page_restore_folders), + page); + + button = GTK_BUTTON (widget); + + widget = mail_config_defaults_page_add_real_folder ( + page, size_group, button, + _("Use a Real Folder for _Trash:"), + _("Choose a folder for deleted messages."), + "real-trash-path", "use-real-trash-path"); + if (widget != NULL) { + gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 2, 1); + gtk_widget_show (widget); + } + + widget = mail_config_defaults_page_add_real_folder ( + page, size_group, button, + _("Use a Real Folder for _Junk:"), + _("Choose a folder for junk messages."), + "real-junk-path", "use-real-junk-path"); + if (widget != NULL) { + gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 2, 1); + gtk_widget_show (widget); + } + + /*** Composing Messages ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Composing Messages"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Alway_s carbon-copy (cc) to:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_margin_left (widget, 12); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property_full ( + composition_ext, "cc", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + mail_config_defaults_page_addrs_to_string, + mail_config_defaults_page_string_to_addrs, + NULL, (GDestroyNotify) NULL); + + text = _("Always _blind carbon-copy (bcc) to:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_margin_left (widget, 12); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property_full ( + composition_ext, "bcc", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + mail_config_defaults_page_addrs_to_string, + mail_config_defaults_page_string_to_addrs, + NULL, (GDestroyNotify) NULL); + + /*** Message Receipts ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Message Receipts"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("S_end message receipts:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_combo_box_text_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1); + gtk_widget_show (widget); + + /* XXX This is a pain in the butt, but we want to avoid hard-coding + * string values from the EMdnResponsePolicy enum class in case + * they change in the future. */ + enum_class = g_type_class_ref (E_TYPE_MDN_RESPONSE_POLICY); + policy = E_MDN_RESPONSE_POLICY_NEVER; + enum_value = g_enum_get_value (enum_class, policy); + g_return_if_fail (enum_value != NULL); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + enum_value->value_nick, _("Never")); + policy = E_MDN_RESPONSE_POLICY_ALWAYS; + enum_value = g_enum_get_value (enum_class, policy); + g_return_if_fail (enum_value != NULL); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + enum_value->value_nick, _("Always")); + policy = E_MDN_RESPONSE_POLICY_ASK; + enum_value = g_enum_get_value (enum_class, policy); + g_return_if_fail (enum_value != NULL); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + enum_value->value_nick, _("Ask for each message")); + g_type_class_unref (enum_class); + + g_object_bind_property_full ( + mdn_ext, "response-policy", + widget, "active-id", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + e_binding_transform_enum_value_to_nick, + e_binding_transform_enum_nick_to_value, + NULL, (GDestroyNotify) NULL); + + g_object_unref (size_group); + + e_extensible_load_extensions (E_EXTENSIBLE (page)); +} + +static void +e_mail_config_defaults_page_class_init (EMailConfigDefaultsPageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigDefaultsPagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_defaults_page_set_property; + object_class->get_property = mail_config_defaults_page_get_property; + object_class->dispose = mail_config_defaults_page_dispose; + object_class->constructed = mail_config_defaults_page_constructed; + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT_SOURCE, + g_param_spec_object ( + "account-source", + "Account Source", + "Mail account source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_IDENTITY_SOURCE, + g_param_spec_object ( + "identity-source", + "Identity Source", + "Mail identity source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SESSION, + g_param_spec_object ( + "session", + "Session", + "Mail session", + E_TYPE_MAIL_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_defaults_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Defaults"); + interface->sort_order = E_MAIL_CONFIG_DEFAULTS_PAGE_SORT_ORDER; +} + +static void +e_mail_config_defaults_page_init (EMailConfigDefaultsPage *page) +{ + page->priv = E_MAIL_CONFIG_DEFAULTS_PAGE_GET_PRIVATE (page); +} + +EMailConfigPage * +e_mail_config_defaults_page_new (EMailSession *session, + ESource *account_source, + ESource *identity_source) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + g_return_val_if_fail (E_IS_SOURCE (account_source), NULL); + g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, + "account-source", account_source, + "identity-source", identity_source, + "session", session, NULL); +} + +EMailSession * +e_mail_config_defaults_page_get_session (EMailConfigDefaultsPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_DEFAULTS_PAGE (page), NULL); + + return page->priv->session; +} + +ESource * +e_mail_config_defaults_page_get_account_source (EMailConfigDefaultsPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_DEFAULTS_PAGE (page), NULL); + + return page->priv->account_source; +} + +ESource * +e_mail_config_defaults_page_get_identity_source (EMailConfigDefaultsPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_DEFAULTS_PAGE (page), NULL); + + return page->priv->identity_source; +} + diff --git a/mail/e-mail-config-defaults-page.h b/mail/e-mail-config-defaults-page.h new file mode 100644 index 0000000000..0f6371ce08 --- /dev/null +++ b/mail/e-mail-config-defaults-page.h @@ -0,0 +1,79 @@ +/* + * e-mail-config-defaults-page.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_CONFIG_DEFAULTS_PAGE_H +#define E_MAIL_CONFIG_DEFAULTS_PAGE_H + +#include <gtk/gtk.h> +#include <libemail-engine/e-mail-session.h> + +#include <mail/e-mail-config-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE \ + (e_mail_config_defaults_page_get_type ()) +#define E_MAIL_CONFIG_DEFAULTS_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPage)) +#define E_MAIL_CONFIG_DEFAULT_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPageClass)) +#define E_IS_MAIL_CONFIG_DEFAULTS_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE)) +#define E_IS_MAIL_CONFIG_DEFAULTS_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE)) +#define E_MAIL_CONFIG_DEFAULTS_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPageClass)) + +#define E_MAIL_CONFIG_DEFAULTS_PAGE_SORT_ORDER (500) + +G_BEGIN_DECLS + +typedef struct _EMailConfigDefaultsPage EMailConfigDefaultsPage; +typedef struct _EMailConfigDefaultsPageClass EMailConfigDefaultsPageClass; +typedef struct _EMailConfigDefaultsPagePrivate EMailConfigDefaultsPagePrivate; + +struct _EMailConfigDefaultsPage { + GtkBox parent; + EMailConfigDefaultsPagePrivate *priv; +}; + +struct _EMailConfigDefaultsPageClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_defaults_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_defaults_page_new (EMailSession *session, + ESource *account_source, + ESource *identity_source); +EMailSession * e_mail_config_defaults_page_get_session + (EMailConfigDefaultsPage *page); +ESource * e_mail_config_defaults_page_get_account_source + (EMailConfigDefaultsPage *page); +ESource * e_mail_config_defaults_page_get_identity_source + (EMailConfigDefaultsPage *page); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_DEFAULTS_PAGE_H */ + diff --git a/mail/e-mail-config-identity-page.c b/mail/e-mail-config-identity-page.c new file mode 100644 index 0000000000..a0920ab1a3 --- /dev/null +++ b/mail/e-mail-config-identity-page.c @@ -0,0 +1,738 @@ +/* + * e-mail-config-identity-page.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-config-identity-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> +#include <libedataserver/e-source-mail-identity.h> + +#include <e-util/e-marshal.h> +#include <misc/e-mail-signature-combo-box.h> +#include <misc/e-mail-signature-editor.h> + +#define E_MAIL_CONFIG_IDENTITY_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPagePrivate)) + +struct _EMailConfigIdentityPagePrivate { + ESource *identity_source; + ESourceRegistry *registry; + gboolean show_account_info; + gboolean show_instructions; + gboolean show_signatures; +}; + +enum { + PROP_0, + PROP_IDENTITY_SOURCE, + PROP_REGISTRY, + PROP_SHOW_ACCOUNT_INFO, + PROP_SHOW_INSTRUCTIONS, + PROP_SHOW_SIGNATURES +}; + +/* Forward Declarations */ +static void e_mail_config_identity_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigIdentityPage, + e_mail_config_identity_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_identity_page_interface_init)) + +static gboolean +mail_config_identity_page_is_email (const gchar *email_address) +{ + const gchar *cp; + + /* Make sure we have a '@' between a name and domain part. */ + cp = strchr (email_address, '@'); + + return (cp != NULL && cp != email_address && *(cp + 1) != '\0'); +} + +static void +mail_config_identity_page_add_signature_cb (GtkButton *button, + EMailConfigIdentityPage *page) +{ + ESourceRegistry *registry; + GtkWidget *editor; + + registry = e_mail_config_identity_page_get_registry (page); + + editor = e_mail_signature_editor_new (registry, NULL); + gtk_window_set_position (GTK_WINDOW (editor), GTK_WIN_POS_CENTER); + gtk_widget_show (editor); +} + +static void +mail_config_identity_page_set_registry (EMailConfigIdentityPage *page, + ESourceRegistry *registry) +{ + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_return_if_fail (page->priv->registry == NULL); + + page->priv->registry = g_object_ref (registry); +} + +static void +mail_config_identity_page_set_identity_source (EMailConfigIdentityPage *page, + ESource *identity_source) +{ + g_return_if_fail (E_IS_SOURCE (identity_source)); + g_return_if_fail (page->priv->identity_source == NULL); + + page->priv->identity_source = g_object_ref (identity_source); +} + +static void +mail_config_identity_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_IDENTITY_SOURCE: + mail_config_identity_page_set_identity_source ( + E_MAIL_CONFIG_IDENTITY_PAGE (object), + g_value_get_object (value)); + return; + + case PROP_REGISTRY: + mail_config_identity_page_set_registry ( + E_MAIL_CONFIG_IDENTITY_PAGE (object), + g_value_get_object (value)); + return; + + case PROP_SHOW_ACCOUNT_INFO: + e_mail_config_identity_page_set_show_account_info ( + E_MAIL_CONFIG_IDENTITY_PAGE (object), + g_value_get_boolean (value)); + return; + + case PROP_SHOW_INSTRUCTIONS: + e_mail_config_identity_page_set_show_instructions ( + E_MAIL_CONFIG_IDENTITY_PAGE (object), + g_value_get_boolean (value)); + return; + + case PROP_SHOW_SIGNATURES: + e_mail_config_identity_page_set_show_signatures ( + E_MAIL_CONFIG_IDENTITY_PAGE (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_identity_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_IDENTITY_SOURCE: + g_value_set_object ( + value, + e_mail_config_identity_page_get_identity_source ( + E_MAIL_CONFIG_IDENTITY_PAGE (object))); + return; + + case PROP_REGISTRY: + g_value_set_object ( + value, + e_mail_config_identity_page_get_registry ( + E_MAIL_CONFIG_IDENTITY_PAGE (object))); + return; + + case PROP_SHOW_ACCOUNT_INFO: + g_value_set_boolean ( + value, + e_mail_config_identity_page_get_show_account_info ( + E_MAIL_CONFIG_IDENTITY_PAGE (object))); + return; + + case PROP_SHOW_INSTRUCTIONS: + g_value_set_boolean ( + value, + e_mail_config_identity_page_get_show_instructions ( + E_MAIL_CONFIG_IDENTITY_PAGE (object))); + return; + + case PROP_SHOW_SIGNATURES: + g_value_set_boolean ( + value, + e_mail_config_identity_page_get_show_signatures ( + E_MAIL_CONFIG_IDENTITY_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_identity_page_dispose (GObject *object) +{ + EMailConfigIdentityPagePrivate *priv; + + priv = E_MAIL_CONFIG_IDENTITY_PAGE_GET_PRIVATE (object); + + if (priv->identity_source != NULL) { + g_object_unref (priv->identity_source); + priv->identity_source = NULL; + } + + if (priv->registry != NULL) { + g_object_unref (priv->registry); + priv->registry = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_identity_page_parent_class)-> + dispose (object); +} + +static void +mail_config_identity_page_constructed (GObject *object) +{ + EMailConfigIdentityPage *page; + ESource *source; + ESourceRegistry *registry; + ESourceMailIdentity *extension; + GtkLabel *label; + GtkWidget *widget; + GtkWidget *container; + GtkSizeGroup *size_group; + const gchar *extension_name; + const gchar *text; + gchar *markup; + + page = E_MAIL_CONFIG_IDENTITY_PAGE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_identity_page_parent_class)-> + constructed (object); + + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + registry = e_mail_config_identity_page_get_registry (page); + source = e_mail_config_identity_page_get_identity_source (page); + extension = e_source_get_extension (source, extension_name); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + gtk_box_set_spacing (GTK_BOX (page), 12); + + /* This keeps all mnemonic labels the same width. */ + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + gtk_size_group_set_ignore_hidden (size_group, TRUE); + + text = _("Please enter your name and email address below. " + "The \"optional\" fields below do not need to be filled " + "in, unless you wish to include this information in email " + "you send."); + widget = gtk_label_new (text); + gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + + g_object_bind_property ( + page, "show-instructions", + widget, "visible", + G_BINDING_SYNC_CREATE); + + /*** Account Information ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + + g_object_bind_property ( + page, "show-account-info", + widget, "visible", + G_BINDING_SYNC_CREATE); + + container = widget; + + text = _("Account Information"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Type the name by which you would like to refer to " + "this account.\nFor example, \"Work\" or \"Personal\"."); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 2, 1); + gtk_widget_show (widget); + + text = _("_Name:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + source, "display-name", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + /* This entry affects the "check-complete" result. */ + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_mail_config_page_changed), page); + + /*** Required Information ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Required Information"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Full Nam_e:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + extension, "name", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + /* This entry affects the "check-complete" result. */ + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_mail_config_page_changed), page); + + text = _("Email _Address:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + extension, "address", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + /* This entry affects the "check-complete" result. */ + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_mail_config_page_changed), page); + + /*** Optional Information ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Optional Information"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 3, 1); + gtk_widget_show (widget); + + text = _("Re_ply-To:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 2, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + extension, "reply-to", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + /* This entry affects the "check-complete" result. */ + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_mail_config_page_changed), page); + + text = _("Or_ganization:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 2, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + extension, "organization", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + text = _("Si_gnature:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + page, "show-signatures", + widget, "visible", + G_BINDING_SYNC_CREATE); + + label = GTK_LABEL (widget); + + widget = e_mail_signature_combo_box_new (registry); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_halign (widget, GTK_ALIGN_START); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 3, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + extension, "signature-uid", + widget, "active-id", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + page, "show-signatures", + widget, "visible", + G_BINDING_SYNC_CREATE); + + text = _("Add Ne_w Signature..."); + widget = gtk_button_new_with_mnemonic (text); + gtk_grid_attach (GTK_GRID (container), widget, 2, 3, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + page, "show-signatures", + widget, "visible", + G_BINDING_SYNC_CREATE); + + g_signal_connect ( + widget, "clicked", + G_CALLBACK (mail_config_identity_page_add_signature_cb), page); + + g_object_unref (size_group); + + e_extensible_load_extensions (E_EXTENSIBLE (page)); +} + +static gboolean +mail_config_identity_page_check_complete (EMailConfigPage *page) +{ + EMailConfigIdentityPage *id_page; + ESource *source; + ESourceMailIdentity *extension; + const gchar *extension_name; + const gchar *name; + const gchar *address; + const gchar *reply_to; + const gchar *display_name; + + id_page = E_MAIL_CONFIG_IDENTITY_PAGE (page); + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + source = e_mail_config_identity_page_get_identity_source (id_page); + extension = e_source_get_extension (source, extension_name); + + name = e_source_mail_identity_get_name (extension); + address = e_source_mail_identity_get_address (extension); + reply_to = e_source_mail_identity_get_reply_to (extension); + + display_name = e_source_get_display_name (source); + + if (name == NULL) + return FALSE; + + if (address == NULL) + return FALSE; + + if (!mail_config_identity_page_is_email (address)) + return FALSE; + + /* A NULL reply_to string is allowed. */ + if (reply_to != NULL && !mail_config_identity_page_is_email (reply_to)) + return FALSE; + + /* Only enforce when account information is visible. */ + if (e_mail_config_identity_page_get_show_account_info (id_page)) + if (display_name == NULL || *display_name == '\0') + return FALSE; + + return TRUE; +} + +static void +e_mail_config_identity_page_class_init (EMailConfigIdentityPageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigIdentityPagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_identity_page_set_property; + object_class->get_property = mail_config_identity_page_get_property; + object_class->dispose = mail_config_identity_page_dispose; + object_class->constructed = mail_config_identity_page_constructed; + + g_object_class_install_property ( + object_class, + PROP_REGISTRY, + g_param_spec_object ( + "registry", + "Registry", + "Registry of data sources", + E_TYPE_SOURCE_REGISTRY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_IDENTITY_SOURCE, + g_param_spec_object ( + "identity-source", + "Identity Source", + "Mail identity source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_ACCOUNT_INFO, + g_param_spec_boolean ( + "show-account-info", + "Show Account Info", + "Show the \"Account Information\" section", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_INSTRUCTIONS, + g_param_spec_boolean ( + "show-instructions", + "Show Instructions", + "Show helpful instructions", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_SIGNATURES, + g_param_spec_boolean ( + "show-signatures", + "Show Signatures", + "Show mail signature options", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_identity_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Identity"); + interface->sort_order = E_MAIL_CONFIG_IDENTITY_PAGE_SORT_ORDER; + interface->check_complete = mail_config_identity_page_check_complete; +} + +static void +e_mail_config_identity_page_init (EMailConfigIdentityPage *page) +{ + page->priv = E_MAIL_CONFIG_IDENTITY_PAGE_GET_PRIVATE (page); +} + +EMailConfigPage * +e_mail_config_identity_page_new (ESourceRegistry *registry, + ESource *identity_source) +{ + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, + "registry", registry, + "identity-source", identity_source, + NULL); +} + +ESourceRegistry * +e_mail_config_identity_page_get_registry (EMailConfigIdentityPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), NULL); + + return page->priv->registry; +} + +ESource * +e_mail_config_identity_page_get_identity_source (EMailConfigIdentityPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), NULL); + + return page->priv->identity_source; +} + +gboolean +e_mail_config_identity_page_get_show_account_info (EMailConfigIdentityPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE); + + return page->priv->show_account_info; +} + +void +e_mail_config_identity_page_set_show_account_info (EMailConfigIdentityPage *page, + gboolean show_account_info) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page)); + + page->priv->show_account_info = show_account_info; + + g_object_notify (G_OBJECT (page), "show-account-info"); +} + +gboolean +e_mail_config_identity_page_get_show_instructions (EMailConfigIdentityPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE); + + return page->priv->show_instructions; +} + +void +e_mail_config_identity_page_set_show_instructions (EMailConfigIdentityPage *page, + gboolean show_instructions) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page)); + + page->priv->show_instructions = show_instructions; + + g_object_notify (G_OBJECT (page), "show-instructions"); +} + +gboolean +e_mail_config_identity_page_get_show_signatures (EMailConfigIdentityPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE); + + return page->priv->show_signatures; +} + +void +e_mail_config_identity_page_set_show_signatures (EMailConfigIdentityPage *page, + gboolean show_signatures) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page)); + + page->priv->show_signatures = show_signatures; + + g_object_notify (G_OBJECT (page), "show-signatures"); +} + diff --git a/mail/e-mail-config-identity-page.h b/mail/e-mail-config-identity-page.h new file mode 100644 index 0000000000..51d879e45f --- /dev/null +++ b/mail/e-mail-config-identity-page.h @@ -0,0 +1,91 @@ +/* + * e-mail-config-identity-page.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_CONFIG_IDENTITY_PAGE_H +#define E_MAIL_CONFIG_IDENTITY_PAGE_H + +#include <gtk/gtk.h> +#include <libedataserver/e-source-registry.h> + +#include <mail/e-mail-config-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_IDENTITY_PAGE \ + (e_mail_config_identity_page_get_type ()) +#define E_MAIL_CONFIG_IDENTITY_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPage)) +#define E_MAIL_CONFIG_IDENTITY_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPageClass)) +#define E_IS_MAIL_CONFIG_IDENTITY_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE)) +#define E_IS_MAIL_CONFIG_IDENTITY_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE)) +#define E_MAIL_CONFIG_IDENTITY_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPageClass)) + +#define E_MAIL_CONFIG_IDENTITY_PAGE_SORT_ORDER (100) + +G_BEGIN_DECLS + +typedef struct _EMailConfigIdentityPage EMailConfigIdentityPage; +typedef struct _EMailConfigIdentityPageClass EMailConfigIdentityPageClass; +typedef struct _EMailConfigIdentityPagePrivate EMailConfigIdentityPagePrivate; + +struct _EMailConfigIdentityPage { + GtkBox parent; + EMailConfigIdentityPagePrivate *priv; +}; + +struct _EMailConfigIdentityPageClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_identity_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_identity_page_new (ESourceRegistry *registry, + ESource *identity_source); +ESourceRegistry * + e_mail_config_identity_page_get_registry + (EMailConfigIdentityPage *page); +ESource * e_mail_config_identity_page_get_identity_source + (EMailConfigIdentityPage *page); +gboolean e_mail_config_identity_page_get_show_account_info + (EMailConfigIdentityPage *page); +void e_mail_config_identity_page_set_show_account_info + (EMailConfigIdentityPage *page, + gboolean show_account_info); +gboolean e_mail_config_identity_page_get_show_instructions + (EMailConfigIdentityPage *page); +void e_mail_config_identity_page_set_show_instructions + (EMailConfigIdentityPage *page, + gboolean show_instructions); +gboolean e_mail_config_identity_page_get_show_signatures + (EMailConfigIdentityPage *page); +void e_mail_config_identity_page_set_show_signatures + (EMailConfigIdentityPage *page, + gboolean show_signatures); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_IDENTITY_PAGE_H */ diff --git a/mail/e-mail-config-lookup-page.c b/mail/e-mail-config-lookup-page.c new file mode 100644 index 0000000000..0154a053b1 --- /dev/null +++ b/mail/e-mail-config-lookup-page.c @@ -0,0 +1,109 @@ +/* + * e-mail-config-lookup-page.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-config-lookup-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +/* Forward Declarations */ +static void e_mail_config_lookup_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigLookupPage, + e_mail_config_lookup_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_lookup_page_interface_init)) + +static void +mail_config_lookup_page_constructed (GObject *object) +{ + EMailConfigLookupPage *page; + GtkWidget *container; + GtkWidget *widget; + const gchar *text; + + page = E_MAIL_CONFIG_LOOKUP_PAGE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_lookup_page_parent_class)-> + constructed (object); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + gtk_box_set_spacing (GTK_BOX (page), 12); + + gtk_widget_set_valign (GTK_WIDGET (page), GTK_ALIGN_FILL); + + widget = gtk_alignment_new (0.5, 0.5, 0.5, 0.5); + gtk_box_pack_start (GTK_BOX (page), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_spinner_new (); + gtk_spinner_start (GTK_SPINNER (widget)); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + text = _("Looking up account details..."); + widget = gtk_label_new (text); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); +} + +static gboolean +mail_config_lookup_page_check_complete (EMailConfigPage *page) +{ + return FALSE; +} + +static void +e_mail_config_lookup_page_class_init (EMailConfigLookupPageClass *class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = mail_config_lookup_page_constructed; +} + +static void +e_mail_config_lookup_page_interface_init (EMailConfigPageInterface *interface) +{ + /* Do not set a title. We don't want this + * page listed in a GtkAssistant sidebar. */ + interface->title = ""; + interface->sort_order = E_MAIL_CONFIG_LOOKUP_PAGE_SORT_ORDER; + interface->page_type = GTK_ASSISTANT_PAGE_CUSTOM; + interface->check_complete = mail_config_lookup_page_check_complete; +} + +static void +e_mail_config_lookup_page_init (EMailConfigLookupPage *page) +{ +} + +EMailConfigPage * +e_mail_config_lookup_page_new () +{ + return g_object_new (E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, NULL); +} diff --git a/mail/e-mail-config-lookup-page.h b/mail/e-mail-config-lookup-page.h new file mode 100644 index 0000000000..bbf9db3892 --- /dev/null +++ b/mail/e-mail-config-lookup-page.h @@ -0,0 +1,73 @@ +/* + * e-mail-config-lookup-page.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_CONFIG_LOOKUP_PAGE_H +#define E_MAIL_CONFIG_LOOKUP_PAGE_H + +#include <gtk/gtk.h> + +#include <mail/e-mail-config-identity-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_LOOKUP_PAGE \ + (e_mail_config_lookup_page_get_type ()) +#define E_MAIL_CONFIG_LOOKUP_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, EMailConfigLookupPage)) +#define E_MAIL_CONFIG_LOOKUP_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, EMailConfigLookupPageClass)) +#define E_IS_MAIL_CONFIG_LOOKUP_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE)) +#define E_IS_MAIL_CONFIG_LOOKUP_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE)) +#define E_MAIL_CONFIG_LOOKUP_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, EMailConfigLookupPageClass)) + +/* Since this is a transient page we define the sort order + * as the previous page's sort order plus a small offset. */ +#define E_MAIL_CONFIG_LOOKUP_PAGE_SORT_ORDER \ + (E_MAIL_CONFIG_IDENTITY_PAGE_SORT_ORDER + 10) + +G_BEGIN_DECLS + +typedef struct _EMailConfigLookupPage EMailConfigLookupPage; +typedef struct _EMailConfigLookupPageClass EMailConfigLookupPageClass; +typedef struct _EMailConfigLookupPagePrivate EMailConfigLookupPagePrivate; + +struct _EMailConfigLookupPage { + GtkBox parent; + EMailConfigLookupPagePrivate *priv; +}; + +struct _EMailConfigLookupPageClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_lookup_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_lookup_page_new (void); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_LOOKUP_PAGE_H */ + diff --git a/mail/e-mail-config-notebook.c b/mail/e-mail-config-notebook.c new file mode 100644 index 0000000000..999ee1baf2 --- /dev/null +++ b/mail/e-mail-config-notebook.c @@ -0,0 +1,783 @@ +/* + * e-mail-config-notebook.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-config-notebook.h" + +#include <libebackend/e-extensible.h> +#include <libedataserver/e-source-goa.h> +#include <libedataserver/e-source-mail-identity.h> + +#include <mail/e-mail-config-defaults-page.h> +#include <mail/e-mail-config-identity-page.h> +#include <mail/e-mail-config-provider-page.h> +#include <mail/e-mail-config-receiving-page.h> +#include <mail/e-mail-config-security-page.h> +#include <mail/e-mail-config-sending-page.h> + +#define E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebookPrivate)) + +typedef struct _AsyncContext AsyncContext; + +struct _EMailConfigNotebookPrivate { + EMailSession *session; + ESource *account_source; + ESource *identity_source; + ESource *transport_source; + ESource *collection_source; +}; + +struct _AsyncContext { + ESourceRegistry *registry; + GCancellable *cancellable; + GQueue *source_queue; +}; + +enum { + PROP_0, + PROP_ACCOUNT_SOURCE, + PROP_COLLECTION_SOURCE, + PROP_COMPLETE, + PROP_IDENTITY_SOURCE, + PROP_SESSION, + PROP_TRANSPORT_SOURCE +}; + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigNotebook, + e_mail_config_notebook, + GTK_TYPE_NOTEBOOK, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL)) + +static void +async_context_free (AsyncContext *async_context) +{ + if (async_context->registry != NULL) + g_object_unref (async_context->registry); + + if (async_context->cancellable != NULL) + g_object_unref (async_context->cancellable); + + g_queue_free_full ( + async_context->source_queue, + (GDestroyNotify) g_object_unref); + + g_slice_free (AsyncContext, async_context); +} + +static void +mail_config_notebook_sort_pages (EMailConfigNotebook *notebook) +{ + GList *list, *link; + gint ii = 0; + + list = g_list_sort ( + gtk_container_get_children (GTK_CONTAINER (notebook)), + (GCompareFunc) e_mail_config_page_compare); + + for (link = list; link != NULL; link = g_list_next (link)) + gtk_notebook_reorder_child ( + GTK_NOTEBOOK (notebook), + GTK_WIDGET (link->data), ii++); + + g_list_free (list); +} + +static void +mail_config_notebook_page_changed (EMailConfigPage *page, + EMailConfigNotebook *notebook) +{ + g_object_notify (G_OBJECT (notebook), "complete"); +} + +static void +mail_config_notebook_set_account_source (EMailConfigNotebook *notebook, + ESource *account_source) +{ + g_return_if_fail (E_IS_SOURCE (account_source)); + g_return_if_fail (notebook->priv->account_source == NULL); + + notebook->priv->account_source = g_object_ref (account_source); +} + +static void +mail_config_notebook_set_collection_source (EMailConfigNotebook *notebook, + ESource *collection_source) +{ + g_return_if_fail (notebook->priv->collection_source == NULL); + + if (collection_source != NULL) { + g_return_if_fail (E_IS_SOURCE (collection_source)); + g_object_ref (collection_source); + } + + notebook->priv->collection_source = collection_source; +} + +static void +mail_config_notebook_set_identity_source (EMailConfigNotebook *notebook, + ESource *identity_source) +{ + g_return_if_fail (E_IS_SOURCE (identity_source)); + g_return_if_fail (notebook->priv->identity_source == NULL); + + notebook->priv->identity_source = g_object_ref (identity_source); +} + +static void +mail_config_notebook_set_session (EMailConfigNotebook *notebook, + EMailSession *session) +{ + g_return_if_fail (E_IS_MAIL_SESSION (session)); + g_return_if_fail (notebook->priv->session == NULL); + + notebook->priv->session = g_object_ref (session); +} + +static void +mail_config_notebook_set_transport_source (EMailConfigNotebook *notebook, + ESource *transport_source) +{ + g_return_if_fail (E_IS_SOURCE (transport_source)); + g_return_if_fail (notebook->priv->transport_source == NULL); + + notebook->priv->transport_source = g_object_ref (transport_source); +} + +static void +mail_config_notebook_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_SOURCE: + mail_config_notebook_set_account_source ( + E_MAIL_CONFIG_NOTEBOOK (object), + g_value_get_object (value)); + return; + + case PROP_COLLECTION_SOURCE: + mail_config_notebook_set_collection_source ( + E_MAIL_CONFIG_NOTEBOOK (object), + g_value_get_object (value)); + return; + + case PROP_IDENTITY_SOURCE: + mail_config_notebook_set_identity_source ( + E_MAIL_CONFIG_NOTEBOOK (object), + g_value_get_object (value)); + return; + + case PROP_SESSION: + mail_config_notebook_set_session ( + E_MAIL_CONFIG_NOTEBOOK (object), + g_value_get_object (value)); + return; + + case PROP_TRANSPORT_SOURCE: + mail_config_notebook_set_transport_source ( + E_MAIL_CONFIG_NOTEBOOK (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_notebook_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_SOURCE: + g_value_set_object ( + value, + e_mail_config_notebook_get_account_source ( + E_MAIL_CONFIG_NOTEBOOK (object))); + return; + + case PROP_COLLECTION_SOURCE: + g_value_set_object ( + value, + e_mail_config_notebook_get_collection_source ( + E_MAIL_CONFIG_NOTEBOOK (object))); + return; + + case PROP_COMPLETE: + g_value_set_boolean ( + value, + e_mail_config_notebook_check_complete ( + E_MAIL_CONFIG_NOTEBOOK (object))); + return; + + case PROP_IDENTITY_SOURCE: + g_value_set_object ( + value, + e_mail_config_notebook_get_identity_source ( + E_MAIL_CONFIG_NOTEBOOK (object))); + return; + + case PROP_SESSION: + g_value_set_object ( + value, + e_mail_config_notebook_get_session ( + E_MAIL_CONFIG_NOTEBOOK (object))); + return; + + case PROP_TRANSPORT_SOURCE: + g_value_set_object ( + value, + e_mail_config_notebook_get_transport_source ( + E_MAIL_CONFIG_NOTEBOOK (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_notebook_dispose (GObject *object) +{ + EMailConfigNotebookPrivate *priv; + + priv = E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE (object); + + if (priv->session != NULL) { + g_object_ref (priv->session); + priv->session = NULL; + } + + if (priv->account_source != NULL) { + g_object_ref (priv->account_source); + priv->account_source = NULL; + } + + if (priv->identity_source != NULL) { + g_object_ref (priv->identity_source); + priv->identity_source = NULL; + } + + if (priv->transport_source != NULL) { + g_object_ref (priv->transport_source); + priv->transport_source = NULL; + } + + if (priv->collection_source != NULL) { + g_object_ref (priv->collection_source); + priv->collection_source = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_notebook_parent_class)-> + dispose (object); +} + +static void +mail_config_notebook_constructed (GObject *object) +{ + EMailConfigNotebook *notebook; + ESource *source; + ESourceRegistry *registry; + ESourceExtension *extension; + ESourceMailIdentity *mail_identity_extension; + EMailConfigServiceBackend *backend; + CamelProvider *provider; + EMailSession *session; + EMailConfigPage *page; + const gchar *extension_name; + gboolean add_receiving_page = TRUE; + gboolean add_sending_page = TRUE; + + notebook = E_MAIL_CONFIG_NOTEBOOK (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_notebook_parent_class)-> + constructed (object); + + session = e_mail_config_notebook_get_session (notebook); + registry = e_mail_session_get_registry (session); + + source = notebook->priv->identity_source; + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + extension = e_source_get_extension (source, extension_name); + mail_identity_extension = E_SOURCE_MAIL_IDENTITY (extension); + + /* If we have a collection source and the collection source + * has a [GNOME Online Accounts] extension, skip the Receiving + * and Sending pages since GOA dictates those settings. */ + source = notebook->priv->collection_source; + if (source != NULL) { + extension_name = E_SOURCE_EXTENSION_GOA; + if (e_source_has_extension (source, extension_name)) { + add_receiving_page = FALSE; + add_sending_page = FALSE; + } + } + + /*** Identity Page ***/ + + page = e_mail_config_identity_page_new ( + registry, notebook->priv->identity_source); + e_mail_config_identity_page_set_show_instructions ( + E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE); + e_mail_config_notebook_add_page (notebook, page); + + /*** Receiving Page ***/ + + page = e_mail_config_receiving_page_new (registry); + backend = e_mail_config_service_page_add_scratch_source ( + E_MAIL_CONFIG_SERVICE_PAGE (page), + notebook->priv->account_source, + notebook->priv->collection_source); + if (add_receiving_page) { + e_mail_config_notebook_add_page (notebook, page); + + g_object_bind_property ( + mail_identity_extension, "address", + page, "email-address", + G_BINDING_SYNC_CREATE); + } + + provider = e_mail_config_service_backend_get_provider (backend); + + /*** Receiving Options (conditional) ***/ + + /* Note: We exclude this page if it has no options, + * but we don't know that until we create it. */ + page = e_mail_config_provider_page_new (backend); + if (e_mail_config_provider_page_is_empty ( + E_MAIL_CONFIG_PROVIDER_PAGE (page))) { + g_object_unref (g_object_ref_sink (page)); + } else { + e_mail_config_notebook_add_page (notebook, page); + } + + /*** Sending Page (conditional) ***/ + + if (!CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) { + page = e_mail_config_sending_page_new (registry); + e_mail_config_service_page_add_scratch_source ( + E_MAIL_CONFIG_SERVICE_PAGE (page), + notebook->priv->transport_source, + notebook->priv->collection_source); + if (add_sending_page) { + e_mail_config_notebook_add_page (notebook, page); + + g_object_bind_property ( + mail_identity_extension, "address", + page, "email-address", + G_BINDING_SYNC_CREATE); + } + } + + /*** Defaults Page ***/ + + page = e_mail_config_defaults_page_new ( + session, + notebook->priv->account_source, + notebook->priv->identity_source); + e_mail_config_notebook_add_page (notebook, page); + + /*** Security Page ***/ + + page = e_mail_config_security_page_new ( + notebook->priv->identity_source); + e_mail_config_notebook_add_page (notebook, page); + + e_extensible_load_extensions (E_EXTENSIBLE (notebook)); +} + +static void +mail_config_notebook_page_removed (GtkNotebook *notebook, + GtkWidget *child, + guint page_num) +{ + /* Do not chain up. GtkNotebook does not implement this method. */ + + if (E_IS_MAIL_CONFIG_PAGE (child)) + g_signal_handlers_disconnect_by_func ( + child, mail_config_notebook_page_changed, + E_MAIL_CONFIG_NOTEBOOK (notebook)); +} + +static void +mail_config_notebook_page_added (GtkNotebook *notebook, + GtkWidget *child, + guint page_num) +{ + /* Do not chain up. GtkNotebook does not implement this method. */ + + if (E_IS_MAIL_CONFIG_PAGE (child)) + g_signal_connect ( + child, "changed", + G_CALLBACK (mail_config_notebook_page_changed), + E_MAIL_CONFIG_NOTEBOOK (notebook)); +} + +static void +e_mail_config_notebook_class_init (EMailConfigNotebookClass *class) +{ + GObjectClass *object_class; + GtkNotebookClass *notebook_class; + + g_type_class_add_private (class, sizeof (EMailConfigNotebookPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_notebook_set_property; + object_class->get_property = mail_config_notebook_get_property; + object_class->dispose = mail_config_notebook_dispose; + object_class->constructed = mail_config_notebook_constructed; + + notebook_class = GTK_NOTEBOOK_CLASS (class); + notebook_class->page_removed = mail_config_notebook_page_removed; + notebook_class->page_added = mail_config_notebook_page_added; + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT_SOURCE, + g_param_spec_object ( + "account-source", + "Account Source", + "Mail account source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_COLLECTION_SOURCE, + g_param_spec_object ( + "collection-source", + "Collection Source", + "Optional collection source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_COMPLETE, + g_param_spec_boolean ( + "complete", + "Complete", + "Whether all required fields are complete", + FALSE, /* default is not used */ + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_IDENTITY_SOURCE, + g_param_spec_object ( + "identity-source", + "Identity Source", + "Mail identity source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SESSION, + g_param_spec_object ( + "session", + "Session", + "Mail session", + E_TYPE_MAIL_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_TRANSPORT_SOURCE, + g_param_spec_object ( + "transport-source", + "Transport Source", + "Mail transport source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_notebook_init (EMailConfigNotebook *notebook) +{ + notebook->priv = E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE (notebook); +} + +GtkWidget * +e_mail_config_notebook_new (EMailSession *session, + ESource *account_source, + ESource *identity_source, + ESource *transport_source, + ESource *collection_source) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + g_return_val_if_fail (E_IS_SOURCE (account_source), NULL); + g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL); + g_return_val_if_fail (E_IS_SOURCE (transport_source), NULL); + + /* A collection source is optional. */ + if (collection_source != NULL) + g_return_val_if_fail (E_IS_SOURCE (collection_source), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_NOTEBOOK, + "session", session, + "account-source", account_source, + "identity-source", identity_source, + "transport-source", transport_source, + "collection-source", collection_source, + NULL); +} + +EMailSession * +e_mail_config_notebook_get_session (EMailConfigNotebook *notebook) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL); + + return notebook->priv->session; +} + +ESource * +e_mail_config_notebook_get_account_source (EMailConfigNotebook *notebook) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL); + + return notebook->priv->account_source; +} + +ESource * +e_mail_config_notebook_get_identity_source (EMailConfigNotebook *notebook) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL); + + return notebook->priv->identity_source; +} + +ESource * +e_mail_config_notebook_get_transport_source (EMailConfigNotebook *notebook) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL); + + return notebook->priv->transport_source; +} + +ESource * +e_mail_config_notebook_get_collection_source (EMailConfigNotebook *notebook) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL); + + return notebook->priv->collection_source; +} + +void +e_mail_config_notebook_add_page (EMailConfigNotebook *notebook, + EMailConfigPage *page) +{ + EMailConfigPageInterface *page_interface; + GtkWidget *tab_label; + + g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook)); + g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page)); + + page_interface = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page); + tab_label = gtk_label_new (page_interface->title); + + gtk_widget_show (GTK_WIDGET (page)); + + gtk_notebook_append_page ( + GTK_NOTEBOOK (notebook), + GTK_WIDGET (page), tab_label); + + mail_config_notebook_sort_pages (notebook); +} + +gboolean +e_mail_config_notebook_check_complete (EMailConfigNotebook *notebook) +{ + GList *list, *link; + gboolean complete = TRUE; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), FALSE); + + list = gtk_container_get_children (GTK_CONTAINER (notebook)); + + for (link = list; link != NULL; link = g_list_next (link)) { + if (E_IS_MAIL_CONFIG_PAGE (link->data)) { + EMailConfigPage *page; + page = E_MAIL_CONFIG_PAGE (link->data); + complete = e_mail_config_page_check_complete (page); + + if (!complete) + break; + } + } + + g_list_free (list); + + return complete; +} + +/********************** e_mail_config_notebook_commit() **********************/ + +static void +mail_config_notebook_commit_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + AsyncContext *async_context; + ESource *next_source; + GError *error = NULL; + + simple = G_SIMPLE_ASYNC_RESULT (user_data); + async_context = g_simple_async_result_get_op_res_gpointer (simple); + + e_source_registry_commit_source_finish ( + E_SOURCE_REGISTRY (object), result, &error); + + if (error != NULL) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + next_source = g_queue_pop_head (async_context->source_queue); + + if (next_source == NULL) { + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + e_source_registry_commit_source ( + async_context->registry, next_source, + async_context->cancellable, + mail_config_notebook_commit_cb, simple); + + g_object_unref (next_source); +} + +void +e_mail_config_notebook_commit (EMailConfigNotebook *notebook, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + AsyncContext *async_context; + ESourceRegistry *registry; + EMailSession *session; + ESource *source; + GList *list, *link; + GQueue *queue; + + g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook)); + + session = e_mail_config_notebook_get_session (notebook); + registry = e_mail_session_get_registry (session); + + queue = g_queue_new (); + + /* Queue the collection data source if one is defined. */ + source = e_mail_config_notebook_get_collection_source (notebook); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + + /* Queue the mail-related data sources for the account. */ + source = e_mail_config_notebook_get_account_source (notebook); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + source = e_mail_config_notebook_get_identity_source (notebook); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + source = e_mail_config_notebook_get_transport_source (notebook); + if (source != NULL) + g_queue_push_tail (queue, g_object_ref (source)); + + list = gtk_container_get_children (GTK_CONTAINER (notebook)); + + /* Tell all EMailConfigPages to commit their UI state to their + * scratch ESources and push any additional data sources on to + * the given source queue, such as calendars or address books + * to be bundled with the mail account. */ + for (link = list; link != NULL; link = g_list_next (link)) { + if (E_IS_MAIL_CONFIG_PAGE (link->data)) { + EMailConfigPage *page; + page = E_MAIL_CONFIG_PAGE (link->data); + e_mail_config_page_commit_changes (page, queue); + } + } + + g_list_free (list); + + async_context = g_slice_new0 (AsyncContext); + async_context->registry = g_object_ref (registry); + async_context->source_queue = queue; /* takes ownership */ + + if (G_IS_CANCELLABLE (cancellable)) + async_context->cancellable = g_object_ref (cancellable); + + simple = g_simple_async_result_new ( + G_OBJECT (notebook), callback, user_data, + e_mail_config_notebook_commit); + + g_simple_async_result_set_op_res_gpointer ( + simple, async_context, (GDestroyNotify) async_context_free); + + source = g_queue_pop_head (async_context->source_queue); + g_return_if_fail (E_IS_SOURCE (source)); + + e_source_registry_commit_source ( + async_context->registry, source, + async_context->cancellable, + mail_config_notebook_commit_cb, simple); + + g_object_unref (source); +} + +gboolean +e_mail_config_notebook_commit_finish (EMailConfigNotebook *notebook, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail ( + g_simple_async_result_is_valid ( + result, G_OBJECT (notebook), + e_mail_config_notebook_commit), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + /* Assume success unless a GError is set. */ + return !g_simple_async_result_propagate_error (simple, error); +} + diff --git a/mail/e-mail-config-notebook.h b/mail/e-mail-config-notebook.h new file mode 100644 index 0000000000..3e816c69b4 --- /dev/null +++ b/mail/e-mail-config-notebook.h @@ -0,0 +1,98 @@ +/* + * e-mail-config-notebook.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_CONFIG_NOTEBOOK_H +#define E_MAIL_CONFIG_NOTEBOOK_H + +#include <gtk/gtk.h> + +#include <libemail-engine/e-mail-session.h> + +#include <mail/e-mail-config-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_NOTEBOOK \ + (e_mail_config_notebook_get_type ()) +#define E_MAIL_CONFIG_NOTEBOOK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebook)) +#define E_MAIL_CONFIG_NOTEBOOK_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebookClass)) +#define E_IS_MAIL_CONFIG_NOTEBOOK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK)) +#define E_IS_MAIL_CONFIG_NOTEBOOK_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_NOTEBOOK)) +#define E_MAIL_CONFIG_NOTEBOOK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebookClass)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigNotebook EMailConfigNotebook; +typedef struct _EMailConfigNotebookClass EMailConfigNotebookClass; +typedef struct _EMailConfigNotebookPrivate EMailConfigNotebookPrivate; + +struct _EMailConfigNotebook { + GtkNotebook parent; + EMailConfigNotebookPrivate *priv; +}; + +struct _EMailConfigNotebookClass { + GtkNotebookClass parent_class; +}; + +GType e_mail_config_notebook_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_config_notebook_new + (EMailSession *session, + ESource *account_source, + ESource *identity_source, + ESource *transport_source, + ESource *collection_source); +EMailSession * e_mail_config_notebook_get_session + (EMailConfigNotebook *notebook); +ESource * e_mail_config_notebook_get_account_source + (EMailConfigNotebook *notebook); +ESource * e_mail_config_notebook_get_identity_source + (EMailConfigNotebook *notebook); +ESource * e_mail_config_notebook_get_transport_source + (EMailConfigNotebook *notebook); +ESource * e_mail_config_notebook_get_collection_source + (EMailConfigNotebook *notebook); +void e_mail_config_notebook_add_page + (EMailConfigNotebook *notebook, + EMailConfigPage *page); +gboolean e_mail_config_notebook_check_complete + (EMailConfigNotebook *notebook); +void e_mail_config_notebook_commit + (EMailConfigNotebook *notebook, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean e_mail_config_notebook_commit_finish + (EMailConfigNotebook *notebook, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_NOTEBOOK_H */ + diff --git a/mail/e-mail-config-page.c b/mail/e-mail-config-page.c new file mode 100644 index 0000000000..29d18e8da6 --- /dev/null +++ b/mail/e-mail-config-page.c @@ -0,0 +1,176 @@ +/* + * e-mail-config-page.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-config-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <e-util/e-marshal.h> + +enum { + CHANGED, + SETUP_DEFAULTS, + CHECK_COMPLETE, + COMMIT_CHANGES, + LAST_SIGNAL +}; + +static gulong signals[LAST_SIGNAL]; + +G_DEFINE_INTERFACE ( + EMailConfigPage, + e_mail_config_page, + GTK_TYPE_WIDGET) + +static gboolean +mail_config_page_check_complete (EMailConfigPage *page) +{ + return TRUE; +} + +static gboolean +mail_config_page_check_complete_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer unused) +{ + gboolean v_boolean; + + /* Abort emission if a handler returns FALSE. */ + v_boolean = g_value_get_boolean (handler_return); + g_value_set_boolean (return_accu, v_boolean); + + return v_boolean; +} + +static void +e_mail_config_page_default_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Untitled"); + interface->page_type = GTK_ASSISTANT_PAGE_CONTENT; + + interface->check_complete = mail_config_page_check_complete; + + signals[CHANGED] = g_signal_new ( + "changed", + G_TYPE_FROM_INTERFACE (interface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailConfigPageInterface, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SETUP_DEFAULTS] = g_signal_new ( + "setup-defaults", + G_TYPE_FROM_INTERFACE (interface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailConfigPageInterface, setup_defaults), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[CHECK_COMPLETE] = g_signal_new ( + "check-complete", + G_TYPE_FROM_INTERFACE (interface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailConfigPageInterface, check_complete), + mail_config_page_check_complete_accumulator, NULL, + e_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + signals[COMMIT_CHANGES] = g_signal_new ( + "commit-changes", + G_TYPE_FROM_INTERFACE (interface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailConfigPageInterface, commit_changes), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); +} + +void +e_mail_config_page_changed (EMailConfigPage *page) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page)); + + g_signal_emit (page, signals[CHANGED], 0); +} + +void +e_mail_config_page_setup_defaults (EMailConfigPage *page) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page)); + + g_signal_emit (page, signals[SETUP_DEFAULTS], 0); +} + +gboolean +e_mail_config_page_check_complete (EMailConfigPage *page) +{ + gboolean complete; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_PAGE (page), FALSE); + + g_signal_emit (page, signals[CHECK_COMPLETE], 0, &complete); + + return complete; +} + +void +e_mail_config_page_commit_changes (EMailConfigPage *page, + GQueue *source_queue) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page)); + g_return_if_fail (source_queue != NULL); + + g_signal_emit (page, signals[COMMIT_CHANGES], 0, source_queue); +} + +gint +e_mail_config_page_compare (GtkWidget *page_a, + GtkWidget *page_b) +{ + EMailConfigPageInterface *interface_a = NULL; + EMailConfigPageInterface *interface_b = NULL; + + if (E_IS_MAIL_CONFIG_PAGE (page_a)) + interface_a = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page_a); + + if (E_IS_MAIL_CONFIG_PAGE (page_b)) + interface_b = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page_b); + + if (interface_a == interface_b) + return 0; + + if (interface_a != NULL && interface_b == NULL) + return -1; + + if (interface_a == NULL && interface_b != NULL) + return 1; + + if (interface_a->sort_order < interface_b->sort_order) + return -1; + + if (interface_a->sort_order > interface_b->sort_order) + return 1; + + return 0; +} + diff --git a/mail/e-mail-config-page.h b/mail/e-mail-config-page.h new file mode 100644 index 0000000000..40a949a2d5 --- /dev/null +++ b/mail/e-mail-config-page.h @@ -0,0 +1,72 @@ +/* + * e-mail-config-page.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_CONFIG_PAGE_H +#define E_MAIL_CONFIG_PAGE_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_PAGE \ + (e_mail_config_page_get_type ()) +#define E_MAIL_CONFIG_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_PAGE, EMailConfigPage)) +#define E_IS_MAIL_CONFIG_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_PAGE)) +#define E_MAIL_CONFIG_PAGE_GET_INTERFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE \ + ((obj), E_TYPE_MAIL_CONFIG_PAGE, EMailConfigPageInterface)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigPage EMailConfigPage; +typedef struct _EMailConfigPageInterface EMailConfigPageInterface; + +struct _EMailConfigPageInterface { + GTypeInterface parent_interface; + + gint sort_order; + const gchar *title; + GtkAssistantPageType page_type; + + /* Signals */ + void (*changed) (EMailConfigPage *page); + void (*setup_defaults) (EMailConfigPage *page); + gboolean (*check_complete) (EMailConfigPage *page); + void (*commit_changes) (EMailConfigPage *page, + GQueue *source_queue); +}; + +GType e_mail_config_page_get_type (void) G_GNUC_CONST; +void e_mail_config_page_changed (EMailConfigPage *page); +void e_mail_config_page_setup_defaults + (EMailConfigPage *page); +gboolean e_mail_config_page_check_complete + (EMailConfigPage *page); +void e_mail_config_page_commit_changes + (EMailConfigPage *page, + GQueue *source_queue); +gint e_mail_config_page_compare (GtkWidget *page_a, + GtkWidget *page_b); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_PAGE_H */ + diff --git a/mail/e-mail-config-provider-page.c b/mail/e-mail-config-provider-page.c new file mode 100644 index 0000000000..1474ff3263 --- /dev/null +++ b/mail/e-mail-config-provider-page.c @@ -0,0 +1,774 @@ +/* + * e-mail-config-provider-page.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-config-provider-page.h" + +#include <config.h> +#include <string.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> +#include <libedataserver/e-data-server-util.h> + +#include <libevolution-utils/e-alert-sink.h> +#include <libevolution-utils/e-alert-dialog.h> +#include <misc/e-activity-bar.h> +#include <misc/e-alert-bar.h> + +#define E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPagePrivate)) + +#define STANDARD_MARGIN 12 +#define DEPENDENCY_MARGIN 24 + +struct _EMailConfigProviderPagePrivate { + EMailConfigServiceBackend *backend; + gboolean is_empty; + + GtkWidget *activity_bar; + GtkWidget *alert_bar; +}; + +enum { + PROP_0, + PROP_BACKEND +}; + +/* Forward Declarations */ +static void e_mail_config_provider_page_alert_sink_init + (EAlertSinkInterface *interface); +static void e_mail_config_provider_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigProviderPage, + e_mail_config_provider_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_ALERT_SINK, + e_mail_config_provider_page_alert_sink_init) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_provider_page_interface_init)) + +static void +mail_config_provider_page_handle_dependency (EMailConfigProviderPage *page, + CamelProviderConfEntry *entry, + GtkWidget *widget) +{ + EMailConfigServiceBackend *backend; + CamelSettings *settings; + GBindingFlags binding_flags = G_BINDING_SYNC_CREATE; + const gchar *depname = entry->depname; + gint margin; + + if (depname == NULL) + return; + + if (*depname == '!') { + binding_flags |= G_BINDING_INVERT_BOOLEAN; + depname++; + } + + backend = e_mail_config_provider_page_get_backend (page); + settings = e_mail_config_service_backend_get_settings (backend); + + g_object_bind_property ( + settings, depname, + widget, "sensitive", + binding_flags); + + /* Further indent the widget to show its dependency. */ + margin = gtk_widget_get_margin_left (widget); + gtk_widget_set_margin_left (widget, margin + DEPENDENCY_MARGIN); +} + +static void +mail_config_provider_page_add_section (EMailConfigProviderPage *page, + CamelProviderConfEntry *entry) +{ + EMailConfigServiceBackend *backend; + CamelProvider *provider; + GtkWidget *widget; + gchar *markup; + + g_return_if_fail (entry->text != NULL); + + backend = e_mail_config_provider_page_get_backend (page); + provider = e_mail_config_service_backend_get_provider (backend); + + markup = g_markup_printf_escaped ("<b>%s</b>", entry->text); + + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + /* Skip the top margin if this is the first entry. */ + if (entry != provider->extra_conf) + gtk_widget_set_margin_top (widget, 6); + + g_free (markup); +} + +static void +mail_config_provider_page_add_checkbox (EMailConfigProviderPage *page, + CamelProviderConfEntry *entry) +{ + EMailConfigServiceBackend *backend; + CamelSettings *settings; + GtkWidget *widget; + + g_return_if_fail (entry->text != NULL); + + backend = e_mail_config_provider_page_get_backend (page); + settings = e_mail_config_service_backend_get_settings (backend); + + widget = gtk_check_button_new_with_mnemonic (entry->text); + gtk_widget_set_margin_left (widget, STANDARD_MARGIN); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_object_bind_property ( + settings, entry->name, + widget, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + mail_config_provider_page_handle_dependency (page, entry, widget); +} + +static void +mail_config_provider_page_add_checkspin (EMailConfigProviderPage *page, + CamelProviderConfEntry *entry) +{ + EMailConfigServiceBackend *backend; + CamelSettings *settings; + GObjectClass *class; + GParamSpec *pspec; + GParamSpec *use_pspec; + GtkAdjustment *adjustment; + GtkWidget *hbox, *spin; + GtkWidget *prefix; + gchar *use_property_name; + gchar *pre, *post; + + g_return_if_fail (entry->text != NULL); + + backend = e_mail_config_provider_page_get_backend (page); + settings = e_mail_config_service_backend_get_settings (backend); + + /* The entry->name property (e.g. "foo") should be numeric for the + * spin button. If a "use" boolean property exists (e.g. "use-foo") + * then a checkbox is also shown. */ + + class = G_OBJECT_GET_CLASS (settings); + pspec = g_object_class_find_property (class, entry->name); + g_return_if_fail (pspec != NULL); + + use_property_name = g_strconcat ("use-", entry->name, NULL); + use_pspec = g_object_class_find_property (class, use_property_name); + if (use_pspec != NULL && use_pspec->value_type != G_TYPE_BOOLEAN) + use_pspec = NULL; + g_free (use_property_name); + + /* Make sure we can convert to and from doubles. */ + g_return_if_fail ( + g_value_type_transformable ( + pspec->value_type, G_TYPE_DOUBLE)); + g_return_if_fail ( + g_value_type_transformable ( + G_TYPE_DOUBLE, pspec->value_type)); + + if (G_IS_PARAM_SPEC_CHAR (pspec)) { + GParamSpecChar *pspec_char; + pspec_char = G_PARAM_SPEC_CHAR (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_char->default_value, + (gdouble) pspec_char->minimum, + (gdouble) pspec_char->maximum, + 1.0, 1.0, 0.0); + + } else if (G_IS_PARAM_SPEC_UCHAR (pspec)) { + GParamSpecUChar *pspec_uchar; + pspec_uchar = G_PARAM_SPEC_UCHAR (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_uchar->default_value, + (gdouble) pspec_uchar->minimum, + (gdouble) pspec_uchar->maximum, + 1.0, 1.0, 0.0); + + } else if (G_IS_PARAM_SPEC_INT (pspec)) { + GParamSpecInt *pspec_int; + pspec_int = G_PARAM_SPEC_INT (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_int->default_value, + (gdouble) pspec_int->minimum, + (gdouble) pspec_int->maximum, + 1.0, 1.0, 0.0); + + } else if (G_IS_PARAM_SPEC_UINT (pspec)) { + GParamSpecUInt *pspec_uint; + pspec_uint = G_PARAM_SPEC_UINT (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_uint->default_value, + (gdouble) pspec_uint->minimum, + (gdouble) pspec_uint->maximum, + 1.0, 1.0, 0.0); + + } else if (G_IS_PARAM_SPEC_LONG (pspec)) { + GParamSpecLong *pspec_long; + pspec_long = G_PARAM_SPEC_LONG (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_long->default_value, + (gdouble) pspec_long->minimum, + (gdouble) pspec_long->maximum, + 1.0, 1.0, 0.0); + + } else if (G_IS_PARAM_SPEC_ULONG (pspec)) { + GParamSpecULong *pspec_ulong; + pspec_ulong = G_PARAM_SPEC_ULONG (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_ulong->default_value, + (gdouble) pspec_ulong->minimum, + (gdouble) pspec_ulong->maximum, + 1.0, 1.0, 0.0); + + } else if (G_IS_PARAM_SPEC_FLOAT (pspec)) { + GParamSpecFloat *pspec_float; + pspec_float = G_PARAM_SPEC_FLOAT (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_float->default_value, + (gdouble) pspec_float->minimum, + (gdouble) pspec_float->maximum, + 1.0, 1.0, 0.0); + + } else if (G_IS_PARAM_SPEC_DOUBLE (pspec)) { + GParamSpecDouble *pspec_double; + pspec_double = G_PARAM_SPEC_DOUBLE (pspec); + adjustment = gtk_adjustment_new ( + (gdouble) pspec_double->default_value, + (gdouble) pspec_double->minimum, + (gdouble) pspec_double->maximum, + 1.0, 1.0, 0.0); + + } else + g_return_if_reached (); + + pre = g_alloca (strlen (entry->text) + 1); + strcpy (pre, entry->text); + post = strstr (pre, "%s"); + if (post != NULL) { + *post = '\0'; + post += 2; + } + + hbox = gtk_hbox_new (FALSE, 3); + gtk_widget_set_margin_left (hbox, STANDARD_MARGIN); + gtk_box_pack_start (GTK_BOX (page), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + if (use_pspec != NULL) { + prefix = gtk_check_button_new_with_mnemonic (pre); + + g_object_bind_property ( + settings, use_pspec->name, + prefix, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + } else { + prefix = gtk_label_new_with_mnemonic (pre); + } + gtk_box_pack_start (GTK_BOX (hbox), prefix, FALSE, TRUE, 0); + gtk_widget_show (prefix); + + spin = gtk_spin_button_new (adjustment, 1.0, 0); + gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, TRUE, 0); + gtk_widget_show (spin); + + g_object_bind_property ( + settings, entry->name, + spin, "value", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + if (use_pspec != NULL) + g_object_bind_property ( + prefix, "active", + spin, "sensitive", + G_BINDING_SYNC_CREATE); + + if (post != NULL) { + GtkWidget *label = gtk_label_new_with_mnemonic (post); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), prefix); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); + gtk_widget_show (label); + } + + mail_config_provider_page_handle_dependency (page, entry, hbox); +} + +static void +mail_config_provider_page_add_entry (EMailConfigProviderPage *page, + CamelProviderConfEntry *entry) +{ + EMailConfigServiceBackend *backend; + CamelSettings *settings; + GtkWidget *hbox; + GtkWidget *input; + GtkWidget *label; + + g_return_if_fail (entry->text != NULL); + + backend = e_mail_config_provider_page_get_backend (page); + settings = e_mail_config_service_backend_get_settings (backend); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_set_spacing (GTK_BOX (hbox), 6); + gtk_widget_set_margin_left (hbox, STANDARD_MARGIN); + gtk_box_pack_start (GTK_BOX (page), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new_with_mnemonic (entry->text); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + input = gtk_entry_new (); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), input); + gtk_box_pack_start (GTK_BOX (hbox), input, TRUE, TRUE, 0); + gtk_widget_show (input); + + g_object_bind_property ( + settings, entry->name, + input, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + input, "sensitive", + label, "sensitive", + G_BINDING_SYNC_CREATE); + + mail_config_provider_page_handle_dependency (page, entry, hbox); +} + +static void +mail_config_provider_page_add_options (EMailConfigProviderPage *page, + CamelProviderConfEntry *entry) +{ + EMailConfigServiceBackend *backend; + CamelProvider *provider; + CamelSettings *settings; + GtkCellRenderer *renderer; + GtkListStore *store; + GtkWidget *hbox; + GtkWidget *combo; + GtkWidget *label; + gchar **tokens; + guint length, ii; + + /* The 'value' string is of the format: + * + * 'nick0:caption0:nick1:caption1:...nickN:captionN' + * + * where 'nick' is the nickname a GEnumValue and 'caption' + * is the localized combo box item displayed to the user. */ + + g_return_if_fail (entry->text != NULL); + g_return_if_fail (entry->value != NULL); + + backend = e_mail_config_provider_page_get_backend (page); + provider = e_mail_config_service_backend_get_provider (backend); + settings = e_mail_config_service_backend_get_settings (backend); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_set_spacing (GTK_BOX (hbox), 6); + gtk_widget_set_margin_left (hbox, STANDARD_MARGIN); + gtk_box_pack_start (GTK_BOX (page), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new_with_mnemonic (entry->text); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + /* 0: 'nick', 1: caption */ + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + + tokens = g_strsplit (entry->value, ":", -1); + length = g_strv_length (tokens); + + /* Take the strings two at a time. */ + for (ii = 0; ii + 1 < length; ii += 2) { + GtkTreeIter iter; + const gchar *nick; + const gchar *caption; + + nick = tokens[ii + 0]; + caption = tokens[ii + 1]; + + /* Localize the caption. */ + caption = dgettext (provider->translation_domain, caption); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, nick, 1, caption, -1); + } + + g_strfreev (tokens); + + combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)); + gtk_combo_box_set_id_column (GTK_COMBO_BOX (combo), 0); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); + gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0); + gtk_widget_show (combo); + + g_object_bind_property_full ( + settings, entry->name, + combo, "active-id", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + e_binding_transform_enum_value_to_nick, + e_binding_transform_enum_nick_to_value, + NULL, (GDestroyNotify) NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE); + gtk_cell_layout_set_attributes ( + GTK_CELL_LAYOUT (combo), renderer, "text", 1, NULL); + + mail_config_provider_page_handle_dependency (page, entry, hbox); +} + +static void +mail_config_provider_page_add_widgets (EMailConfigProviderPage *page) +{ + EMailConfigServiceBackend *backend; + CamelProviderConfEntry *entries; + CamelProvider *provider; + GtkWidget *frame; + GtkWidget *widget; + gint ii; + + /* Note the "text" member of each CamelProviderConfEntry is + * already localized, so we can use it directly in widgets. */ + + backend = e_mail_config_provider_page_get_backend (page); + provider = e_mail_config_service_backend_get_provider (backend); + g_return_if_fail (provider != NULL); + + entries = provider->extra_conf; + + /* Loop until we see CAMEL_PROVIDER_CONF_END. */ + for (ii = 0; entries[ii].type != CAMEL_PROVIDER_CONF_END; ii++) { + + /* Skip entries with no name. */ + if (entries[ii].name == NULL) + continue; + + switch (entries[ii].type) { + case CAMEL_PROVIDER_CONF_SECTION_START: + mail_config_provider_page_add_section ( + page, &entries[ii]); + break; + + case CAMEL_PROVIDER_CONF_CHECKBOX: + mail_config_provider_page_add_checkbox ( + page, &entries[ii]); + break; + + case CAMEL_PROVIDER_CONF_CHECKSPIN: + mail_config_provider_page_add_checkspin ( + page, &entries[ii]); + break; + + case CAMEL_PROVIDER_CONF_ENTRY: + mail_config_provider_page_add_entry ( + page, &entries[ii]); + break; + + case CAMEL_PROVIDER_CONF_OPTIONS: + mail_config_provider_page_add_options ( + page, &entries[ii]); + break; + + default: + break; /* skip it */ + } + } + + /* So far only Evolution-EWS uses the activity and alert + * bars, but other packages may someday find it handy. */ + + widget = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN); + gtk_box_pack_end (GTK_BOX (page), widget, FALSE, FALSE, 0); + /* Visibility is bound to the EActivityBar. */ + + frame = widget; + + widget = e_activity_bar_new (); + gtk_container_add (GTK_CONTAINER (frame), widget); + page->priv->activity_bar = widget; /* not referenced */ + /* EActivity controls its own visibility. */ + + g_object_bind_property ( + widget, "visible", + frame, "visible", + G_BINDING_SYNC_CREATE); + + widget = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN); + gtk_box_pack_end (GTK_BOX (page), widget, FALSE, FALSE, 0); + /* Visibility is bound to the EAlertBar. */ + + frame = widget; + + widget = e_alert_bar_new (); + gtk_container_add (GTK_CONTAINER (frame), widget); + page->priv->alert_bar = widget; /* not referenced */ + /* EAlertBar controls its own visibility. */ + + g_object_bind_property ( + widget, "visible", + frame, "visible", + G_BINDING_SYNC_CREATE); +} + +static void +mail_config_provider_page_set_backend (EMailConfigProviderPage *page, + EMailConfigServiceBackend *backend) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + g_return_if_fail (page->priv->backend == NULL); + + page->priv->backend = g_object_ref (backend); +} + +static void +mail_config_provider_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_BACKEND: + mail_config_provider_page_set_backend ( + E_MAIL_CONFIG_PROVIDER_PAGE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_provider_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_BACKEND: + g_value_set_object ( + value, + e_mail_config_provider_page_get_backend ( + E_MAIL_CONFIG_PROVIDER_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_provider_page_dispose (GObject *object) +{ + EMailConfigProviderPagePrivate *priv; + + priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (object); + + if (priv->backend != NULL) { + g_object_unref (priv->backend); + priv->backend = NULL; + } + + /* Chain up parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_provider_page_parent_class)-> + dispose (object); +} + +static void +mail_config_provider_page_constructed (GObject *object) +{ + EMailConfigProviderPage *page; + EMailConfigServiceBackend *backend; + CamelProvider *provider; + + page = E_MAIL_CONFIG_PROVIDER_PAGE (object); + + /* Chain up parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_provider_page_parent_class)-> + constructed (object); + + gtk_box_set_spacing (GTK_BOX (object), 6); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (object), GTK_ORIENTATION_VERTICAL); + + backend = e_mail_config_provider_page_get_backend (page); + provider = e_mail_config_service_backend_get_provider (backend); + + if (provider != NULL && provider->extra_conf != NULL) + mail_config_provider_page_add_widgets (page); + else + page->priv->is_empty = TRUE; + + e_extensible_load_extensions (E_EXTENSIBLE (page)); +} + +static void +mail_config_provider_page_submit_alert (EAlertSink *alert_sink, + EAlert *alert) +{ + EMailConfigProviderPagePrivate *priv; + EAlertBar *alert_bar; + GtkWidget *dialog; + gpointer parent; + + priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (alert_sink); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (alert_sink)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + switch (e_alert_get_message_type (alert)) { + case GTK_MESSAGE_INFO: + case GTK_MESSAGE_WARNING: + case GTK_MESSAGE_ERROR: + alert_bar = E_ALERT_BAR (priv->alert_bar); + e_alert_bar_add_alert (alert_bar, alert); + break; + + default: + dialog = e_alert_dialog_new (parent, alert); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + break; + } +} + +static void +e_mail_config_provider_page_class_init (EMailConfigProviderPageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailConfigProviderPagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_provider_page_set_property; + object_class->get_property = mail_config_provider_page_get_property; + object_class->dispose = mail_config_provider_page_dispose; + object_class->constructed = mail_config_provider_page_constructed; + + g_object_class_install_property ( + object_class, + PROP_BACKEND, + g_param_spec_object ( + "backend", + "Backend", + "Service backend to generate options from", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_provider_page_alert_sink_init (EAlertSinkInterface *interface) +{ + interface->submit_alert = mail_config_provider_page_submit_alert; +} + +static void +e_mail_config_provider_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Receiving Options"); + interface->sort_order = E_MAIL_CONFIG_PROVIDER_PAGE_SORT_ORDER; +} + +static void +e_mail_config_provider_page_init (EMailConfigProviderPage *page) +{ + page->priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (page); +} + +EMailConfigPage * +e_mail_config_provider_page_new (EMailConfigServiceBackend *backend) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, + "backend", backend, NULL); +} + +gboolean +e_mail_config_provider_page_is_empty (EMailConfigProviderPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), TRUE); + + return page->priv->is_empty; +} + +EMailConfigServiceBackend * +e_mail_config_provider_page_get_backend (EMailConfigProviderPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), NULL); + + return page->priv->backend; +} + +EActivity * +e_mail_config_provider_page_new_activity (EMailConfigProviderPage *page) +{ + EActivity *activity; + EActivityBar *activity_bar; + GCancellable *cancellable; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), NULL); + + /* Clear any previous alerts. */ + e_alert_bar_clear (E_ALERT_BAR (page->priv->alert_bar)); + + activity = e_activity_new (); + + e_activity_set_alert_sink (activity, E_ALERT_SINK (page)); + + cancellable = camel_operation_new (); + e_activity_set_cancellable (activity, cancellable); + g_object_unref (cancellable); + + activity_bar = E_ACTIVITY_BAR (page->priv->activity_bar); + e_activity_bar_set_activity (activity_bar, activity); + + return activity; +} + diff --git a/mail/e-mail-config-provider-page.h b/mail/e-mail-config-provider-page.h new file mode 100644 index 0000000000..fbbdf7f34a --- /dev/null +++ b/mail/e-mail-config-provider-page.h @@ -0,0 +1,81 @@ +/* + * e-mail-config-provider-page.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_CONFIG_PROVIDER_PAGE_H +#define E_MAIL_CONFIG_PROVIDER_PAGE_H + +#include <gtk/gtk.h> +#include <camel/camel.h> +#include <libedataserver/e-source-registry.h> + +#include <e-util/e-activity.h> +#include <mail/e-mail-config-page.h> +#include <mail/e-mail-config-service-backend.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_PROVIDER_PAGE \ + (e_mail_config_provider_page_get_type ()) +#define E_MAIL_CONFIG_PROVIDER_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPage)) +#define E_MAIL_CONFIG_PROVIDER_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPageClass)) +#define E_IS_MAIL_CONFIG_PROVIDER_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE)) +#define E_IS_MAIL_CONFIG_PROVIDER_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE)) +#define E_MAIL_CONFIG_PROVIDER_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPageClass)) + +#define E_MAIL_CONFIG_PROVIDER_PAGE_SORT_ORDER (300) + +G_BEGIN_DECLS + +typedef struct _EMailConfigProviderPage EMailConfigProviderPage; +typedef struct _EMailConfigProviderPageClass EMailConfigProviderPageClass; +typedef struct _EMailConfigProviderPagePrivate EMailConfigProviderPagePrivate; + +struct _EMailConfigProviderPage { + GtkBox parent; + EMailConfigProviderPagePrivate *priv; +}; + +struct _EMailConfigProviderPageClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_provider_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_provider_page_new + (EMailConfigServiceBackend *backend); +gboolean e_mail_config_provider_page_is_empty + (EMailConfigProviderPage *page); +EMailConfigServiceBackend * + e_mail_config_provider_page_get_backend + (EMailConfigProviderPage *page); +EActivity * e_mail_config_provider_page_new_activity + (EMailConfigProviderPage *page); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_PROVIDER_PAGE_H */ diff --git a/mail/e-mail-config-receiving-page.c b/mail/e-mail-config-receiving-page.c new file mode 100644 index 0000000000..7106f20414 --- /dev/null +++ b/mail/e-mail-config-receiving-page.c @@ -0,0 +1,70 @@ +/* + * e-mail-config-receiving-page.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-config-receiving-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libedataserver/e-source-mail-account.h> + +/* Forward Declarations */ +static void e_mail_config_receiving_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigReceivingPage, + e_mail_config_receiving_page, + E_TYPE_MAIL_CONFIG_SERVICE_PAGE, + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_receiving_page_interface_init)) + +static void +e_mail_config_receiving_page_class_init (EMailConfigReceivingPageClass *class) +{ + EMailConfigServicePageClass *service_page_class; + + service_page_class = E_MAIL_CONFIG_SERVICE_PAGE_CLASS (class); + service_page_class->extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + service_page_class->provider_type = CAMEL_PROVIDER_STORE; + service_page_class->default_backend_name = "imapx"; +} + +static void +e_mail_config_receiving_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Receiving Email"); + interface->sort_order = E_MAIL_CONFIG_RECEIVING_PAGE_SORT_ORDER; +} + +static void +e_mail_config_receiving_page_init (EMailConfigReceivingPage *page) +{ +} + +EMailConfigPage * +e_mail_config_receiving_page_new (ESourceRegistry *registry) +{ + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_RECEIVING_PAGE, + "registry", registry, NULL); +} + diff --git a/mail/e-mail-config-receiving-page.h b/mail/e-mail-config-receiving-page.h new file mode 100644 index 0000000000..626da30a49 --- /dev/null +++ b/mail/e-mail-config-receiving-page.h @@ -0,0 +1,69 @@ +/* + * e-mail-config-receiving-page.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_CONFIG_RECEIVING_PAGE_H +#define E_MAIL_CONFIG_RECEIVING_PAGE_H + +#include <mail/e-mail-config-page.h> +#include <mail/e-mail-config-service-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_RECEIVING_PAGE \ + (e_mail_config_receiving_page_get_type ()) +#define E_MAIL_CONFIG_RECEIVING_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE, EMailConfigReceivingPage)) +#define E_MAIL_CONFIG_RECEIVING_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE, EMailConfigReceivingPageClass)) +#define E_IS_MAIL_CONFIG_RECEIVING_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE)) +#define E_IS_MAIL_CONFIG_RECEIVING_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE)) +#define E_MAIL_CONFIG_RECEIVING_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE, EMailConfigReceivingPageClass)) + +#define E_MAIL_CONFIG_RECEIVING_PAGE_SORT_ORDER (200) + +G_BEGIN_DECLS + +typedef struct _EMailConfigReceivingPage EMailConfigReceivingPage; +typedef struct _EMailConfigReceivingPageClass EMailConfigReceivingPageClass; +typedef struct _EMailConfigReceivingPagePrivate EMailConfigReceivingPagePrivate; + +struct _EMailConfigReceivingPage { + EMailConfigServicePage parent; +}; + +struct _EMailConfigReceivingPageClass { + EMailConfigServicePageClass parent_class; +}; + +GType e_mail_config_receiving_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_receiving_page_new + (ESourceRegistry *registry); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_RECEIVING_PAGE_H */ + diff --git a/mail/e-mail-config-security-page.c b/mail/e-mail-config-security-page.c new file mode 100644 index 0000000000..911e40bb47 --- /dev/null +++ b/mail/e-mail-config-security-page.c @@ -0,0 +1,672 @@ +/* + * e-mail-config-security-page.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-config-security-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> +#include <libedataserver/e-source-mail-composition.h> +#include <libedataserver/e-source-openpgp.h> +#include <libedataserver/e-source-smime.h> + +#if defined (HAVE_NSS) +#include <smime/gui/e-cert-selector.h> +#endif /* HAVE_NSS */ + +#define E_MAIL_CONFIG_SECURITY_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPagePrivate)) + +struct _EMailConfigSecurityPagePrivate { + ESource *identity_source; +}; + +enum { + PROP_0, + PROP_IDENTITY_SOURCE +}; + +/* Forward Declarations */ +static void e_mail_config_security_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigSecurityPage, + e_mail_config_security_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_security_page_interface_init)) + +static gboolean +mail_config_security_page_string_has_text (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer unused) +{ + const gchar *string; + gchar *stripped; + + string = g_value_get_string (source_value); + + if (string == NULL) + string = ""; + + stripped = g_strstrip (g_strdup (string)); + g_value_set_boolean (target_value, *stripped != '\0'); + g_free (stripped); + + return TRUE; +} + +static void +mail_config_security_page_cert_selected (ECertSelector *selector, + const gchar *key, + GtkEntry *entry) +{ + if (key != NULL) + gtk_entry_set_text (entry, key); + + gtk_widget_destroy (GTK_WIDGET (selector)); +} + +static void +mail_config_security_page_select_encrypt_cert (GtkButton *button, + GtkEntry *entry) +{ + GtkWidget *selector; + gpointer parent; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (button)); + parent = GTK_IS_WIDGET (parent) ? parent : NULL; + + selector = e_cert_selector_new ( + E_CERT_SELECTOR_RECIPIENT, + gtk_entry_get_text (entry)); + gtk_window_set_transient_for ( + GTK_WINDOW (selector), parent); + gtk_widget_show (selector); + + g_signal_connect ( + selector, "selected", + G_CALLBACK (mail_config_security_page_cert_selected), + entry); +} + +static void +mail_config_security_page_select_sign_cert (GtkButton *button, + GtkEntry *entry) +{ + GtkWidget *selector; + gpointer parent; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (button)); + parent = GTK_IS_WIDGET (parent) ? parent : NULL; + + selector = e_cert_selector_new ( + E_CERT_SELECTOR_SIGNER, + gtk_entry_get_text (entry)); + gtk_window_set_transient_for ( + GTK_WINDOW (selector), parent); + gtk_widget_show (selector); + + g_signal_connect ( + selector, "selected", + G_CALLBACK (mail_config_security_page_cert_selected), + entry); +} + +static void +mail_config_security_page_clear_cert (GtkButton *button, + GtkEntry *entry) +{ + gtk_entry_set_text (entry, ""); +} + +static void +mail_config_security_page_set_identity_source (EMailConfigSecurityPage *page, + ESource *identity_source) +{ + g_return_if_fail (E_IS_SOURCE (identity_source)); + g_return_if_fail (page->priv->identity_source == NULL); + + page->priv->identity_source = g_object_ref (identity_source); +} + +static void +mail_config_security_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_IDENTITY_SOURCE: + mail_config_security_page_set_identity_source ( + E_MAIL_CONFIG_SECURITY_PAGE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_security_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_IDENTITY_SOURCE: + g_value_set_object ( + value, + e_mail_config_security_page_get_identity_source ( + E_MAIL_CONFIG_SECURITY_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_security_page_dispose (GObject *object) +{ + EMailConfigSecurityPagePrivate *priv; + + priv = E_MAIL_CONFIG_SECURITY_PAGE_GET_PRIVATE (object); + + if (priv->identity_source != NULL) { + g_object_unref (priv->identity_source); + priv->identity_source = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_security_page_parent_class)-> + dispose (object); +} + +static void +mail_config_security_page_constructed (GObject *object) +{ + EMailConfigSecurityPage *page; + ESource *source; + ESourceMailComposition *composition_ext; + ESourceOpenPGP *openpgp_ext; + GtkEntry *entry; + GtkLabel *label; + GtkWidget *widget; + GtkWidget *container; + GtkSizeGroup *size_group; + const gchar *extension_name; + const gchar *text; + gchar *markup; + +#if defined (HAVE_NSS) + ESourceSMIME *smime_ext; +#endif /* HAVE_NSS */ + + page = E_MAIL_CONFIG_SECURITY_PAGE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_security_page_parent_class)-> + constructed (object); + + source = e_mail_config_security_page_get_identity_source (page); + + extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION; + composition_ext = e_source_get_extension (source, extension_name); + + extension_name = E_SOURCE_EXTENSION_OPENPGP; + openpgp_ext = e_source_get_extension (source, extension_name); + +#if defined (HAVE_NSS) + extension_name = E_SOURCE_EXTENSION_SMIME; + smime_ext = e_source_get_extension (source, extension_name); +#endif /* HAVE_NSS */ + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + gtk_box_set_spacing (GTK_BOX (page), 12); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + /*** General ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("General"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1); + gtk_widget_show (widget); + + text = _("_Do not sign meeting requests (for Outlook compatibility)"); + widget = gtk_check_button_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + composition_ext, "sign-imip", + widget, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + /*** Pretty Good Privacy (OpenPGP) ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Pretty Good Privacy (OpenPGP)"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1); + gtk_widget_show (widget); + + text = _("OpenPGP _Key ID:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + openpgp_ext, "key-id", + widget, "text", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + text = _("Si_gning algorithm:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_combo_box_text_new (); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "", _("Default")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha1", _("SHA1")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha256", _("SHA256")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha384", _("SHA384")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha512", _("SHA512")); + gtk_widget_set_halign (widget, GTK_ALIGN_START); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + openpgp_ext, "signing-algorithm", + widget, "active-id", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + /* Make sure the combo box has an active item. */ + if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (widget)) == NULL) + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + + text = _("Al_ways sign outgoing messages when using this account"); + widget = gtk_check_button_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 2, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + openpgp_ext, "sign-by-default", + widget, "active", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + text = _("Always encrypt to _myself when sending encrypted messages"); + widget = gtk_check_button_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 2, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + openpgp_ext, "encrypt-to-self", + widget, "active", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + text = _("Always _trust keys in my keyring when encrypting"); + widget = gtk_check_button_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 2, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + openpgp_ext, "always-trust", + widget, "active", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + +#if defined (HAVE_NSS) + + /*** Security MIME (S/MIME) ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Secure MIME (S/MIME)"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 4, 1); + gtk_widget_show (widget); + + text = _("Sig_ning certificate:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + smime_ext, "signing-certificate", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + entry = GTK_ENTRY (widget); + + widget = gtk_button_new_with_label (_("Select")); + gtk_grid_attach (GTK_GRID (container), widget, 2, 1, 1, 1); + gtk_widget_show (widget); + + g_signal_connect ( + widget, "clicked", + G_CALLBACK (mail_config_security_page_select_sign_cert), + entry); + + widget = gtk_button_new_from_stock (GTK_STOCK_CLEAR); + gtk_grid_attach (GTK_GRID (container), widget, 3, 1, 1, 1); + gtk_widget_show (widget); + + g_signal_connect ( + widget, "clicked", + G_CALLBACK (mail_config_security_page_clear_cert), + entry); + + text = _("Signing _algorithm:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_combo_box_text_new (); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "", _("Default")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha1", _("SHA1")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha256", _("SHA256")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha384", _("SHA384")); + gtk_combo_box_text_append ( + GTK_COMBO_BOX_TEXT (widget), + "sha512", _("SHA512")); + gtk_widget_set_halign (widget, GTK_ALIGN_START); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + smime_ext, "signing-algorithm", + widget, "active-id", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + /* Make sure the combo box has an active item. */ + if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (widget)) == NULL) + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + + text = _("Always sign outgoing messages when using this account"); + widget = gtk_check_button_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 4, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + smime_ext, "sign-by-default", + widget, "active", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + g_object_bind_property_full ( + smime_ext, "signing-certificate", + widget, "sensitive", + G_BINDING_SYNC_CREATE, + mail_config_security_page_string_has_text, + NULL, + NULL, (GDestroyNotify) NULL); + + /* Add extra padding between signing stuff and encryption stuff. */ + gtk_widget_set_margin_bottom (widget, 6); + + text = _("Encryption certificate:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_size_group_add_widget (size_group, widget); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 4, 1, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + smime_ext, "encryption-certificate", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + entry = GTK_ENTRY (widget); + + widget = gtk_button_new_with_label (_("Select")); + gtk_grid_attach (GTK_GRID (container), widget, 2, 4, 1, 1); + gtk_widget_show (widget); + + g_signal_connect ( + widget, "clicked", + G_CALLBACK (mail_config_security_page_select_encrypt_cert), + entry); + + widget = gtk_button_new_from_stock (GTK_STOCK_CLEAR); + gtk_grid_attach (GTK_GRID (container), widget, 3, 4, 1, 1); + gtk_widget_show (widget); + + g_signal_connect ( + widget, "clicked", + G_CALLBACK (mail_config_security_page_clear_cert), + entry); + + text = _("Always encrypt outgoing messages when using this account"); + widget = gtk_check_button_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 4, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + smime_ext, "encrypt-by-default", + widget, "active", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + g_object_bind_property_full ( + smime_ext, "encryption-certificate", + widget, "sensitive", + G_BINDING_SYNC_CREATE, + mail_config_security_page_string_has_text, + NULL, + NULL, (GDestroyNotify) NULL); + + text = _("Always encrypt to myself when sending encrypted messages"); + widget = gtk_check_button_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_grid_attach (GTK_GRID (container), widget, 0, 6, 4, 1); + gtk_widget_show (widget); + + g_object_bind_property ( + smime_ext, "encrypt-to-self", + widget, "active", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL); + + g_object_bind_property_full ( + smime_ext, "encryption-certificate", + widget, "sensitive", + G_BINDING_SYNC_CREATE, + mail_config_security_page_string_has_text, + NULL, + NULL, (GDestroyNotify) NULL); + +#endif /* HAVE_NSS */ + + g_object_unref (size_group); + + e_extensible_load_extensions (E_EXTENSIBLE (page)); +} + +static void +e_mail_config_security_page_class_init (EMailConfigSecurityPageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigSecurityPagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_security_page_set_property; + object_class->get_property = mail_config_security_page_get_property; + object_class->dispose = mail_config_security_page_dispose; + object_class->constructed = mail_config_security_page_constructed; + + g_object_class_install_property ( + object_class, + PROP_IDENTITY_SOURCE, + g_param_spec_object ( + "identity-source", + "Identity Source", + "Mail identity source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_security_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Security"); + interface->sort_order = E_MAIL_CONFIG_SECURITY_PAGE_SORT_ORDER; +} + +static void +e_mail_config_security_page_init (EMailConfigSecurityPage *page) +{ + page->priv = E_MAIL_CONFIG_SECURITY_PAGE_GET_PRIVATE (page); +} + +EMailConfigPage * +e_mail_config_security_page_new (ESource *identity_source) +{ + g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_SECURITY_PAGE, + "identity-source", identity_source, NULL); +} + +ESource * +e_mail_config_security_page_get_identity_source (EMailConfigSecurityPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SECURITY_PAGE (page), NULL); + + return page->priv->identity_source; +} + diff --git a/mail/e-mail-config-security-page.h b/mail/e-mail-config-security-page.h new file mode 100644 index 0000000000..79174eaed0 --- /dev/null +++ b/mail/e-mail-config-security-page.h @@ -0,0 +1,73 @@ +/* + * e-mail-config-security-page.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_CONFIG_SECURITY_PAGE_H +#define E_MAIL_CONFIG_SECURITY_PAGE_H + +#include <gtk/gtk.h> +#include <libedataserver/e-source.h> + +#include <mail/e-mail-config-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_SECURITY_PAGE \ + (e_mail_config_security_page_get_type ()) +#define E_MAIL_CONFIG_SECURITY_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPage)) +#define E_MAIL_CONFIG_SECURITY_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPageClass)) +#define E_IS_MAIL_CONFIG_SECURITY_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE)) +#define E_IS_MAIL_CONFIG_SECURITY_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_SECURITY_PAGE)) +#define E_MAIL_CONFIG_SECURITY_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPageClass)) + +#define E_MAIL_CONFIG_SECURITY_PAGE_SORT_ORDER (600) + +G_BEGIN_DECLS + +typedef struct _EMailConfigSecurityPage EMailConfigSecurityPage; +typedef struct _EMailConfigSecurityPageClass EMailConfigSecurityPageClass; +typedef struct _EMailConfigSecurityPagePrivate EMailConfigSecurityPagePrivate; + +struct _EMailConfigSecurityPage { + GtkBox parent; + EMailConfigSecurityPagePrivate *priv; +}; + +struct _EMailConfigSecurityPageClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_security_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_security_page_new (ESource *identity_source); +ESource * e_mail_config_security_page_get_identity_source + (EMailConfigSecurityPage *page); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_SECURITY_PAGE_H */ + diff --git a/mail/e-mail-config-sending-page.c b/mail/e-mail-config-sending-page.c new file mode 100644 index 0000000000..198a3ea4ac --- /dev/null +++ b/mail/e-mail-config-sending-page.c @@ -0,0 +1,70 @@ +/* + * e-mail-config-sending-page.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-config-sending-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libedataserver/e-source-mail-transport.h> + +/* Forward Declarations */ +static void e_mail_config_sending_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigSendingPage, + e_mail_config_sending_page, + E_TYPE_MAIL_CONFIG_SERVICE_PAGE, + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_sending_page_interface_init)) + +static void +e_mail_config_sending_page_class_init (EMailConfigSendingPageClass *class) +{ + EMailConfigServicePageClass *service_page_class; + + service_page_class = E_MAIL_CONFIG_SERVICE_PAGE_CLASS (class); + service_page_class->extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; + service_page_class->provider_type = CAMEL_PROVIDER_TRANSPORT; + service_page_class->default_backend_name = "smtp"; +} + +static void +e_mail_config_sending_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Sending Email"); + interface->sort_order = E_MAIL_CONFIG_SENDING_PAGE_SORT_ORDER; +} + +static void +e_mail_config_sending_page_init (EMailConfigSendingPage *page) +{ +} + +EMailConfigPage * +e_mail_config_sending_page_new (ESourceRegistry *registry) +{ + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_SENDING_PAGE, + "registry", registry, NULL); +} + diff --git a/mail/e-mail-config-sending-page.h b/mail/e-mail-config-sending-page.h new file mode 100644 index 0000000000..4727602c95 --- /dev/null +++ b/mail/e-mail-config-sending-page.h @@ -0,0 +1,68 @@ +/* + * e-mail-config-sending-page.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_CONFIG_SENDING_PAGE_H +#define E_MAIL_CONFIG_SENDING_PAGE_H + +#include <mail/e-mail-config-page.h> +#include <mail/e-mail-config-service-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_SENDING_PAGE \ + (e_mail_config_sending_page_get_type ()) +#define E_MAIL_CONFIG_SENDING_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_SENDING_PAGE, EMailConfigSendingPage)) +#define E_MAIL_CONFIG_SENDING_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_SENDING_PAGE, EMailConfigSendingPageClass)) +#define E_IS_MAIL_CONFIG_SENDING_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_SENDING_PAGE)) +#define E_IS_MAIL_CONFIG_SENDING_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_SENDING_PAGE)) +#define E_MAIL_CONFIG_SENDING_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_SENDING_PAGE, EMailConfigSendingPageClass)) + +#define E_MAIL_CONFIG_SENDING_PAGE_SORT_ORDER (400) + +G_BEGIN_DECLS + +typedef struct _EMailConfigSendingPage EMailConfigSendingPage; +typedef struct _EMailConfigSendingPageClass EMailConfigSendingPageClass; +typedef struct _EMailConfigSendingPagePrivate EMailConfigSendingPagePrivate; + +struct _EMailConfigSendingPage { + EMailConfigServicePage parent; +}; + +struct _EMailConfigSendingPageClass { + EMailConfigServicePageClass parent_class; +}; + +GType e_mail_config_sending_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_sending_page_new (ESourceRegistry *registry); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_SENDING_PAGE_H */ + diff --git a/mail/e-mail-config-service-backend.c b/mail/e-mail-config-service-backend.c new file mode 100644 index 0000000000..a4c97fcd18 --- /dev/null +++ b/mail/e-mail-config-service-backend.c @@ -0,0 +1,514 @@ +/* + * e-mail-config-service-backend.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-config-service-backend.h" + +#include <libedataserver/e-source-camel.h> +#include <libedataserver/e-source-backend.h> +#include <libedataserver/e-source-collection.h> + +#include <mail/e-mail-config-receiving-page.h> +#include <mail/e-mail-config-sending-page.h> + +#define E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackendPrivate)) + +struct _EMailConfigServiceBackendPrivate { + ESource *source; + ESource *collection; +}; + +enum { + PROP_0, + PROP_COLLECTION, + PROP_SELECTABLE, + PROP_SOURCE +}; + +G_DEFINE_ABSTRACT_TYPE ( + EMailConfigServiceBackend, + e_mail_config_service_backend, + E_TYPE_EXTENSION) + +static void +mail_config_service_backend_init_collection (EMailConfigServiceBackend *backend) +{ + EMailConfigServiceBackendClass *class; + + /* Use the new_collection() method to initialize the "collection" + * property. This assumes we're editing a new account. If we're + * editing an existing account, the initial "collection" property + * value should be overridden with the existing collection source. */ + + g_return_if_fail (backend->priv->collection == NULL); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_if_fail (class->new_collection != NULL); + + backend->priv->collection = class->new_collection (backend); +} + +static void +mail_config_service_backend_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_COLLECTION: + e_mail_config_service_backend_set_collection ( + E_MAIL_CONFIG_SERVICE_BACKEND (object), + g_value_get_object (value)); + return; + + case PROP_SOURCE: + e_mail_config_service_backend_set_source ( + E_MAIL_CONFIG_SERVICE_BACKEND (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_service_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_COLLECTION: + g_value_set_object ( + value, + e_mail_config_service_backend_get_collection ( + E_MAIL_CONFIG_SERVICE_BACKEND (object))); + return; + + case PROP_SELECTABLE: + g_value_set_boolean ( + value, + e_mail_config_service_backend_get_selectable ( + E_MAIL_CONFIG_SERVICE_BACKEND (object))); + return; + + case PROP_SOURCE: + g_value_set_object ( + value, + e_mail_config_service_backend_get_source ( + E_MAIL_CONFIG_SERVICE_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_service_backend_dispose (GObject *object) +{ + EMailConfigServiceBackendPrivate *priv; + + priv = E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE (object); + + if (priv->source != NULL) { + g_object_unref (priv->source); + priv->source = NULL; + } + + if (priv->collection != NULL) { + g_object_unref (priv->collection); + priv->collection = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_service_backend_parent_class)-> + dispose (object); +} + +static void +mail_config_service_backend_constructed (GObject *object) +{ + EMailConfigServiceBackend *backend; + + backend = E_MAIL_CONFIG_SERVICE_BACKEND (object); + mail_config_service_backend_init_collection (backend); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_service_backend_parent_class)-> + constructed (object); +} + +static gboolean +mail_config_service_backend_get_selectable (EMailConfigServiceBackend *backend) +{ + EMailConfigServicePage *page; + CamelProvider *provider; + gboolean selectable = TRUE; + + page = e_mail_config_service_backend_get_page (backend); + provider = e_mail_config_service_backend_get_provider (backend); + + if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) + selectable = E_IS_MAIL_CONFIG_RECEIVING_PAGE (page); + + return selectable; +} + +static ESource * +mail_config_service_backend_new_collection (EMailConfigServiceBackend *backend) +{ + /* This is typically only used for groupware backends. */ + return NULL; +} + +static void +mail_config_service_backend_insert_widgets (EMailConfigServiceBackend *backend, + GtkBox *parent) +{ + /* does nothing */ +} + +static void +mail_config_service_backend_setup_defaults (EMailConfigServiceBackend *backend) +{ + /* does nothing */ +} + +static gboolean +mail_config_service_backend_auto_configure (EMailConfigServiceBackend *backend, + EMailAutoconfig *autoconfig) +{ + return FALSE; +} + +static gboolean +mail_config_service_backend_check_complete (EMailConfigServiceBackend *backend) +{ + return TRUE; +} + +static void +mail_config_service_backend_commit_changes (EMailConfigServiceBackend *backend) +{ + /* does nothing */ +} + +static void +e_mail_config_service_backend_class_init (EMailConfigServiceBackendClass *class) +{ + GObjectClass *object_class; + EExtensionClass *extension_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigServiceBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_service_backend_set_property; + object_class->get_property = mail_config_service_backend_get_property; + object_class->dispose = mail_config_service_backend_dispose; + object_class->constructed = mail_config_service_backend_constructed; + + extension_class = E_EXTENSION_CLASS (class); + extension_class->extensible_type = E_TYPE_MAIL_CONFIG_SERVICE_PAGE; + + class->get_selectable = mail_config_service_backend_get_selectable; + class->new_collection = mail_config_service_backend_new_collection; + class->insert_widgets = mail_config_service_backend_insert_widgets; + class->setup_defaults = mail_config_service_backend_setup_defaults; + class->auto_configure = mail_config_service_backend_auto_configure; + class->check_complete = mail_config_service_backend_check_complete; + class->commit_changes = mail_config_service_backend_commit_changes; + + g_object_class_install_property ( + object_class, + PROP_COLLECTION, + g_param_spec_object ( + "collection", + "Collection", + "Optional collection ESource", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SELECTABLE, + g_param_spec_boolean ( + "selectable", + "Selectable", + "Whether the backend is user selectable", + TRUE, /* not applied */ + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SOURCE, + g_param_spec_object ( + "source", + "Source", + "The ESource being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_service_backend_init (EMailConfigServiceBackend *backend) +{ + backend->priv = E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE (backend); +} + +EMailConfigServicePage * +e_mail_config_service_backend_get_page (EMailConfigServiceBackend *backend) +{ + EExtensible *extensible; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + extensible = e_extension_get_extensible (E_EXTENSION (backend)); + + return E_MAIL_CONFIG_SERVICE_PAGE (extensible); +} + +ESource * +e_mail_config_service_backend_get_source (EMailConfigServiceBackend *backend) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + return backend->priv->source; +} + +void +e_mail_config_service_backend_set_source (EMailConfigServiceBackend *backend, + ESource *source) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + + if (source != NULL) { + g_return_if_fail (E_IS_SOURCE (source)); + g_object_ref (source); + } + + if (backend->priv->source != NULL) + g_object_unref (backend->priv->source); + + backend->priv->source = source; + + g_object_notify (G_OBJECT (backend), "source"); +} + +ESource * +e_mail_config_service_backend_get_collection (EMailConfigServiceBackend *backend) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + return backend->priv->collection; +} + +void +e_mail_config_service_backend_set_collection (EMailConfigServiceBackend *backend, + ESource *collection) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + + if (collection != NULL) { + g_return_if_fail (E_IS_SOURCE (collection)); + g_object_ref (collection); + } + + if (backend->priv->collection != NULL) + g_object_unref (backend->priv->collection); + + backend->priv->collection = collection; + + g_object_notify (G_OBJECT (backend), "collection"); +} + +CamelProvider * +e_mail_config_service_backend_get_provider (EMailConfigServiceBackend *backend) +{ + EMailConfigServiceBackendClass *class; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_val_if_fail (class->backend_name != NULL, NULL); + + return camel_provider_get (class->backend_name, NULL); +} + +CamelSettings * +e_mail_config_service_backend_get_settings (EMailConfigServiceBackend *backend) +{ + ESource *source; + ESourceCamel *camel_extension = NULL; + EMailConfigServicePage *page; + EMailConfigServicePageClass *page_class; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + page = e_mail_config_service_backend_get_page (backend); + page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page); + + /* Which ESource do we pull the CamelSettings from? This is a + * little tricky because we have to handle the following cases: + * + * 1) A stand-alone mail account. + * + * 2) A collection with a specialized backend (e.g. ews). + * + * 3) A collection that uses standard backends (e.g. yahoo). + * + * So the semantics are as follows. They work for now but may + * need further tweaking as we support more collection types. + * + * 1) If the service backend defines a collection source, + * assume the CamelSettings will be pulled from there. + * + * 2) If we have a collection source, try extracting the + * ESourceCamel extension for the collection source's + * backend name. + * + * 3) If steps 1 or 2 fail, pull the CamelSettings from + * the service backend's own scratch source. + */ + + source = e_mail_config_service_backend_get_collection (backend); + if (source != NULL) { + ESourceBackend *backend_extension; + const gchar *backend_name; + const gchar *extension_name; + + extension_name = E_SOURCE_EXTENSION_COLLECTION; + backend_extension = + e_source_get_extension (source, extension_name); + backend_name = + e_source_backend_get_backend_name (backend_extension); + + extension_name = + e_source_camel_get_extension_name (backend_name); + camel_extension = + e_source_get_extension (source, extension_name); + } + + if (camel_extension == NULL) { + ESourceBackend *backend_extension; + const gchar *backend_name; + const gchar *extension_name; + + source = e_mail_config_service_backend_get_source (backend); + + extension_name = page_class->extension_name; + backend_extension = + e_source_get_extension (source, extension_name); + backend_name = + e_source_backend_get_backend_name (backend_extension); + + extension_name = + e_source_camel_get_extension_name (backend_name); + camel_extension = + e_source_get_extension (source, extension_name); + } + + return e_source_camel_get_settings (camel_extension); +} + +gboolean +e_mail_config_service_backend_get_selectable (EMailConfigServiceBackend *backend) +{ + EMailConfigServiceBackendClass *class; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_val_if_fail (class->get_selectable != NULL, FALSE); + + return class->get_selectable (backend); +} + +void +e_mail_config_service_backend_insert_widgets (EMailConfigServiceBackend *backend, + GtkBox *parent) +{ + EMailConfigServiceBackendClass *class; + + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + g_return_if_fail (GTK_IS_BOX (parent)); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_if_fail (class->insert_widgets != NULL); + + class->insert_widgets (backend, parent); +} + +void +e_mail_config_service_backend_setup_defaults (EMailConfigServiceBackend *backend) +{ + EMailConfigServiceBackendClass *class; + + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_if_fail (class->setup_defaults != NULL); + + return class->setup_defaults (backend); +} + +gboolean +e_mail_config_service_backend_auto_configure (EMailConfigServiceBackend *backend, + EMailAutoconfig *autoconfig) +{ + EMailConfigServiceBackendClass *class; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE); + g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_val_if_fail (class->auto_configure != NULL, FALSE); + + return class->auto_configure (backend, autoconfig); +} + +gboolean +e_mail_config_service_backend_check_complete (EMailConfigServiceBackend *backend) +{ + EMailConfigServiceBackendClass *class; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_val_if_fail (class->check_complete != NULL, FALSE); + + return class->check_complete (backend); +} + +void +e_mail_config_service_backend_commit_changes (EMailConfigServiceBackend *backend) +{ + EMailConfigServiceBackendClass *class; + + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_return_if_fail (class->commit_changes != NULL); + + class->commit_changes (backend); +} + diff --git a/mail/e-mail-config-service-backend.h b/mail/e-mail-config-service-backend.h new file mode 100644 index 0000000000..6ba4ad3d13 --- /dev/null +++ b/mail/e-mail-config-service-backend.h @@ -0,0 +1,121 @@ +/* + * e-mail-config-service-backend.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_CONFIG_SERVICE_BACKEND_H +#define E_MAIL_CONFIG_SERVICE_BACKEND_H + +#include <gtk/gtk.h> +#include <camel/camel.h> +#include <libebackend/e-extension.h> +#include <libedataserver/e-source.h> + +#include <mail/e-mail-autoconfig.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_SERVICE_BACKEND \ + (e_mail_config_service_backend_get_type ()) +#define E_MAIL_CONFIG_SERVICE_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackend)) +#define E_MAIL_CONFIG_SERVICE_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackendClass)) +#define E_IS_MAIL_CONFIG_SERVICE_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND)) +#define E_IS_MAIL_CONFIG_SERVICE_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND)) +#define E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackendClass)) + +G_BEGIN_DECLS + +struct _EMailConfigServicePage; + +typedef struct _EMailConfigServiceBackend EMailConfigServiceBackend; +typedef struct _EMailConfigServiceBackendClass EMailConfigServiceBackendClass; +typedef struct _EMailConfigServiceBackendPrivate EMailConfigServiceBackendPrivate; + +struct _EMailConfigServiceBackend { + EExtension parent; + EMailConfigServiceBackendPrivate *priv; +}; + +struct _EMailConfigServiceBackendClass { + EExtensionClass parent_class; + + const gchar *backend_name; + + gboolean (*get_selectable) + (EMailConfigServiceBackend *backend); + ESource * (*new_collection) + (EMailConfigServiceBackend *backend); + void (*insert_widgets) + (EMailConfigServiceBackend *backend, + GtkBox *parent); + void (*setup_defaults) + (EMailConfigServiceBackend *backend); + gboolean (*auto_configure) + (EMailConfigServiceBackend *backend, + EMailAutoconfig *autoconfig); + gboolean (*check_complete) + (EMailConfigServiceBackend *backend); + void (*commit_changes) + (EMailConfigServiceBackend *backend); +}; + +GType e_mail_config_service_backend_get_type + (void) G_GNUC_CONST; +struct _EMailConfigServicePage * + e_mail_config_service_backend_get_page + (EMailConfigServiceBackend *backend); +ESource * e_mail_config_service_backend_get_source + (EMailConfigServiceBackend *backend); +void e_mail_config_service_backend_set_source + (EMailConfigServiceBackend *backend, + ESource *source); +ESource * e_mail_config_service_backend_get_collection + (EMailConfigServiceBackend *backend); +void e_mail_config_service_backend_set_collection + (EMailConfigServiceBackend *backend, + ESource *collection); +CamelProvider * e_mail_config_service_backend_get_provider + (EMailConfigServiceBackend *backend); +CamelSettings * e_mail_config_service_backend_get_settings + (EMailConfigServiceBackend *backend); +gboolean e_mail_config_service_backend_get_selectable + (EMailConfigServiceBackend *backend); +void e_mail_config_service_backend_insert_widgets + (EMailConfigServiceBackend *backend, + GtkBox *parent); +void e_mail_config_service_backend_setup_defaults + (EMailConfigServiceBackend *backend); +gboolean e_mail_config_service_backend_auto_configure + (EMailConfigServiceBackend *backend, + EMailAutoconfig *autoconfig); +gboolean e_mail_config_service_backend_check_complete + (EMailConfigServiceBackend *backend); +void e_mail_config_service_backend_commit_changes + (EMailConfigServiceBackend *backend); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_SERVICE_BACKEND_H */ + diff --git a/mail/e-mail-config-service-notebook.c b/mail/e-mail-config-service-notebook.c new file mode 100644 index 0000000000..757cd902da --- /dev/null +++ b/mail/e-mail-config-service-notebook.c @@ -0,0 +1,365 @@ +/* + * e-mail-config-service-notebook.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-config-service-notebook.h" + +#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebookPrivate)) + +#define CHILD_BACKEND_KEY_FORMAT \ + "__e_mail_config_service_notebook_%p_child_backend__" + +struct _EMailConfigServiceNotebookPrivate { + EMailConfigServiceBackend *active_backend; + gchar *child_backend_key; +}; + +enum { + PROP_0, + PROP_ACTIVE_BACKEND +}; + +enum { + PROP_CHILD_0, + PROP_CHILD_BACKEND +}; + +G_DEFINE_TYPE ( + EMailConfigServiceNotebook, + e_mail_config_service_notebook, + GTK_TYPE_NOTEBOOK) + +static void +mail_config_service_notebook_set_child_backend (EMailConfigServiceNotebook *notebook, + GtkWidget *child, + EMailConfigServiceBackend *backend) +{ + const gchar *key; + + key = notebook->priv->child_backend_key; + + if (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)) + g_object_set_data_full ( + G_OBJECT (child), key, + g_object_ref (backend), + (GDestroyNotify) g_object_unref); +} + +static EMailConfigServiceBackend * +mail_config_service_notebook_get_child_backend (EMailConfigServiceNotebook *notebook, + GtkWidget *child) +{ + const gchar *key; + + key = notebook->priv->child_backend_key; + + return g_object_get_data (G_OBJECT (child), key); +} + +static gboolean +mail_config_service_notebook_page_num_to_backend (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer user_data) +{ + EMailConfigServiceBackend *backend; + GtkNotebook *notebook; + GtkWidget *child; + gint page_num; + + /* The binding's source and target are the same instance. */ + notebook = GTK_NOTEBOOK (g_binding_get_source (binding)); + + page_num = g_value_get_int (source_value); + child = gtk_notebook_get_nth_page (notebook, page_num); + + if (child != NULL) + backend = mail_config_service_notebook_get_child_backend ( + E_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), child); + else + backend = NULL; + + g_value_set_object (target_value, backend); + + return TRUE; +} + +static gboolean +mail_config_service_notebook_backend_to_page_num (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer user_data) +{ + EMailConfigServiceBackend *backend; + GtkNotebook *notebook; + gint n_pages, ii; + + /* The binding's source and target are the same instance. */ + notebook = GTK_NOTEBOOK (g_binding_get_source (binding)); + + backend = g_value_get_object (source_value); + n_pages = gtk_notebook_get_n_pages (notebook); + + for (ii = 0; ii < n_pages; ii++) { + GtkWidget *child; + EMailConfigServiceBackend *candidate; + + child = gtk_notebook_get_nth_page (notebook, ii); + candidate = mail_config_service_notebook_get_child_backend ( + E_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), child); + + if (backend == candidate) { + g_value_set_int (target_value, ii); + return TRUE; + } + } + + return FALSE; +} + +static void +mail_config_service_notebook_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE_BACKEND: + e_mail_config_service_notebook_set_active_backend ( + E_MAIL_CONFIG_SERVICE_NOTEBOOK (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_service_notebook_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE_BACKEND: + g_value_set_object ( + value, + e_mail_config_service_notebook_get_active_backend ( + E_MAIL_CONFIG_SERVICE_NOTEBOOK (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_service_notebook_dispose (GObject *object) +{ + EMailConfigServiceNotebookPrivate *priv; + + priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (object); + + if (priv->active_backend != NULL) { + g_object_unref (priv->active_backend); + priv->active_backend = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)-> + dispose (object); +} + +static void +mail_config_service_notebook_finalize (GObject *object) +{ + EMailConfigServiceNotebookPrivate *priv; + + priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (object); + + g_free (priv->child_backend_key); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)-> + finalize (object); +} + +static void +mail_config_service_notebook_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)-> + constructed (object); + + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (object), FALSE); + + /* Current page is still -1 so skip G_BINDING_SYNC_CREATE. */ + g_object_bind_property_full ( + object, "page", + object, "active-backend", + G_BINDING_BIDIRECTIONAL, + mail_config_service_notebook_page_num_to_backend, + mail_config_service_notebook_backend_to_page_num, + NULL, (GDestroyNotify) NULL); +} + +static void +mail_config_service_notebook_set_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CHILD_BACKEND: + mail_config_service_notebook_set_child_backend ( + E_MAIL_CONFIG_SERVICE_NOTEBOOK (container), + child, g_value_get_object (value)); + return; + } + + GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID ( + container, property_id, pspec); +} + +static void +mail_config_service_notebook_get_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CHILD_BACKEND: + g_value_set_object ( + value, + mail_config_service_notebook_get_child_backend ( + E_MAIL_CONFIG_SERVICE_NOTEBOOK (container), child)); + return; + } + + GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID ( + container, property_id, pspec); +} + +static void +e_mail_config_service_notebook_class_init (EMailConfigServiceNotebookClass *class) +{ + GObjectClass *object_class; + GtkContainerClass *container_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigServiceNotebookPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_service_notebook_set_property; + object_class->get_property = mail_config_service_notebook_get_property; + object_class->dispose = mail_config_service_notebook_dispose; + object_class->finalize = mail_config_service_notebook_finalize; + object_class->constructed = mail_config_service_notebook_constructed; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->set_child_property = mail_config_service_notebook_set_child_property; + container_class->get_child_property = mail_config_service_notebook_get_child_property; + + g_object_class_install_property ( + object_class, + PROP_ACTIVE_BACKEND, + g_param_spec_object ( + "active-backend", + "Active Backend", + "The service backend for the current page", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /* Child property for notebook pages. */ + gtk_container_class_install_child_property ( + container_class, + PROP_CHILD_BACKEND, + g_param_spec_object ( + "backend", + "Backend", + "The service backend for this page", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_service_notebook_init (EMailConfigServiceNotebook *notebook) +{ + gchar *key; + + notebook->priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (notebook); + + key = g_strdup_printf (CHILD_BACKEND_KEY_FORMAT, notebook); + notebook->priv->child_backend_key = key; +} + +GtkWidget * +e_mail_config_service_notebook_new (void) +{ + return g_object_new (E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, NULL); +} + +gint +e_mail_config_service_notebook_add_page (EMailConfigServiceNotebook *notebook, + EMailConfigServiceBackend *backend, + GtkWidget *child) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), -1); + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), -1); + g_return_val_if_fail (GTK_IS_WIDGET (child), -1); + + gtk_widget_show (child); + + mail_config_service_notebook_set_child_backend ( + notebook, child, backend); + + return gtk_notebook_append_page (GTK_NOTEBOOK (notebook), child, NULL); +} + +EMailConfigServiceBackend * +e_mail_config_service_notebook_get_active_backend (EMailConfigServiceNotebook *notebook) +{ + g_return_val_if_fail ( + E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), NULL); + + return notebook->priv->active_backend; +} + +void +e_mail_config_service_notebook_set_active_backend (EMailConfigServiceNotebook *notebook, + EMailConfigServiceBackend *backend) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook)); + + if (backend != NULL) { + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + g_object_ref (backend); + } + + if (notebook->priv->active_backend != NULL) + g_object_unref (notebook->priv->active_backend); + + notebook->priv->active_backend = backend; + + g_object_notify (G_OBJECT (notebook), "active-backend"); +} + diff --git a/mail/e-mail-config-service-notebook.h b/mail/e-mail-config-service-notebook.h new file mode 100644 index 0000000000..db339e9a93 --- /dev/null +++ b/mail/e-mail-config-service-notebook.h @@ -0,0 +1,77 @@ +/* + * e-mail-config-service-notebook.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_CONFIG_SERVICE_NOTEBOOK_H +#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_H + +#include <gtk/gtk.h> +#include <mail/e-mail-config-service-backend.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK \ + (e_mail_config_service_notebook_get_type ()) +#define E_MAIL_CONFIG_SERVICE_NOTEBOOK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebook)) +#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebookClass)) +#define E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK)) +#define E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK)) +#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebookClass)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigServiceNotebook EMailConfigServiceNotebook; +typedef struct _EMailConfigServiceNotebookClass EMailConfigServiceNotebookClass; +typedef struct _EMailConfigServiceNotebookPrivate EMailConfigServiceNotebookPrivate; + +struct _EMailConfigServiceNotebook { + GtkNotebook parent; + EMailConfigServiceNotebookPrivate *priv; +}; + +struct _EMailConfigServiceNotebookClass { + GtkNotebookClass parent_class; +}; + +GType e_mail_config_service_notebook_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_config_service_notebook_new + (void); +gint e_mail_config_service_notebook_add_page + (EMailConfigServiceNotebook *notebook, + EMailConfigServiceBackend *backend, + GtkWidget *child); +EMailConfigServiceBackend * + e_mail_config_service_notebook_get_active_backend + (EMailConfigServiceNotebook *notebook); +void e_mail_config_service_notebook_set_active_backend + (EMailConfigServiceNotebook *notebook, + EMailConfigServiceBackend *backend); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_SERVICE_NOTEBOOK_H */ + diff --git a/mail/e-mail-config-service-page.c b/mail/e-mail-config-service-page.c new file mode 100644 index 0000000000..1f53ed5ddb --- /dev/null +++ b/mail/e-mail-config-service-page.c @@ -0,0 +1,1039 @@ +/* + * e-mail-config-service-page.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-config-service-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <camel/camel.h> +#include <libebackend/e-extensible.h> +#include <libedataserver/e-source-backend.h> + +#include <libevolution-utils/e-alert-sink.h> +#include <libevolution-utils/e-alert-dialog.h> +#include <misc/e-activity-bar.h> +#include <misc/e-alert-bar.h> + +#include <mail/e-mail-config-page.h> +#include <mail/e-mail-config-service-notebook.h> + +#define E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePagePrivate)) + +/* Used for autoconfiguration. */ +#define POP3_BACKEND_NAME "pop" +#define IMAP_BACKEND_NAME "imapx" +#define SMTP_BACKEND_NAME "smtp" + +typedef struct _Candidate Candidate; + +struct _EMailConfigServicePagePrivate { + ESourceRegistry *registry; + EMailConfigServiceBackend *active_backend; + gchar *email_address; + + GHashTable *backends; + GPtrArray *candidates; + + /* Hidden candidates are not listed in the + * combo box but can still be accessed through + * e_mail_config_service_page_lookup_backend(). */ + GPtrArray *hidden_candidates; + + GtkWidget *type_combo; + GtkWidget *type_label; + GtkWidget *desc_label; + GtkWidget *notebook; + GtkWidget *activity_bar; + GtkWidget *alert_bar; + + /* Combo box list store */ + GtkListStore *list_store; +}; + +struct _Candidate { + gchar *name; + EMailConfigServiceBackend *backend; + + CamelProvider *provider; + CamelSettings *settings; + gulong settings_notify_handler_id; + + GtkWidget *widget; +}; + +enum { + PROP_0, + PROP_ACTIVE_BACKEND, + PROP_EMAIL_ADDRESS, + PROP_REGISTRY +}; + +enum { + COLUMN_BACKEND_NAME, + COLUMN_DISPLAY_NAME, + COLUMN_SELECTABLE, + NUM_COLUMNS +}; + +/* Forward Declarations */ +static void e_mail_config_service_page_alert_sink_init + (EAlertSinkInterface *interface); +static void e_mail_config_service_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE ( + EMailConfigServicePage, + e_mail_config_service_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_ALERT_SINK, + e_mail_config_service_page_alert_sink_init) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_service_page_interface_init)) + +static void +mail_config_service_page_settings_notify_cb (CamelSettings *settings, + GParamSpec *pspec, + EMailConfigPage *page) +{ + e_mail_config_page_changed (page); +} + +static Candidate * +mail_config_service_page_new_candidate (EMailConfigServicePage *page, + ESource *scratch_source, + ESource *opt_collection) +{ + Candidate *candidate; + CamelProvider *provider; + CamelSettings *settings; + ESourceBackend *extension; + EMailConfigServiceBackend *backend; + EMailConfigServicePageClass *class; + const gchar *extension_name; + const gchar *backend_name; + gulong handler_id; + + /* Get the backend name for this scratch source. */ + class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page); + extension_name = class->extension_name; + extension = e_source_get_extension (scratch_source, extension_name); + backend_name = e_source_backend_get_backend_name (extension); + g_return_val_if_fail (backend_name != NULL, NULL); + + /* Make sure we have a corresponding EMailConfigServicePageBackend. */ + backend = g_hash_table_lookup (page->priv->backends, backend_name); + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL); + + /* Make sure we have a corresponding CamelProvider. */ + provider = e_mail_config_service_backend_get_provider (backend); + g_return_val_if_fail (provider != NULL, NULL); + + /* Need to give the backend a scratch source and (if provided) a + * scratch collection source before we can extract a CamelSettings + * instance, since the CamelSettings instance comes from either the + * scratch collection source or else the scratch source. */ + e_mail_config_service_backend_set_source (backend, scratch_source); + if (opt_collection != NULL) + e_mail_config_service_backend_set_collection ( + backend, opt_collection); + + /* Make sure we have a corresponding CamelSettings. */ + settings = e_mail_config_service_backend_get_settings (backend); + g_return_val_if_fail (CAMEL_IS_SETTINGS (settings), NULL); + + candidate = g_slice_new0 (Candidate); + candidate->name = g_strdup (backend_name); + candidate->backend = g_object_ref (backend); + candidate->provider = provider; + candidate->settings = g_object_ref (settings); + + /* Remove the backend so it can't be reused. If another scratch + * source with the same backend name gets added, the hash table + * lookup will fail and emit a runtime warning, which we want. */ + g_hash_table_remove (page->priv->backends, backend_name); + + /* Emit "changed" signals for subsequent CamelSettings changes. */ + handler_id = g_signal_connect ( + candidate->settings, "notify", + G_CALLBACK (mail_config_service_page_settings_notify_cb), page); + candidate->settings_notify_handler_id = handler_id; + + return candidate; +} + +static void +mail_config_service_page_free_candidate (Candidate *candidate) +{ + g_free (candidate->name); + + if (candidate->backend != NULL) + g_object_unref (candidate->backend); + + if (candidate->settings != NULL) { + g_signal_handler_disconnect ( + candidate->settings, + candidate->settings_notify_handler_id); + g_object_unref (candidate->settings); + } + + if (candidate->widget != NULL) + g_object_unref (candidate->widget); + + g_slice_free (Candidate, candidate); +} + +static void +mail_config_service_page_init_backends (EMailConfigServicePage *page) +{ + GList *list, *iter; + + page->priv->backends = g_hash_table_new_full ( + (GHashFunc) g_str_hash, + (GEqualFunc) g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + e_extensible_load_extensions (E_EXTENSIBLE (page)); + + list = e_extensible_list_extensions ( + E_EXTENSIBLE (page), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND); + + for (iter = list; iter != NULL; iter = g_list_next (iter)) { + EMailConfigServiceBackend *backend; + EMailConfigServiceBackendClass *class; + + backend = E_MAIL_CONFIG_SERVICE_BACKEND (iter->data); + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + + if (class->backend_name != NULL) + g_hash_table_insert ( + page->priv->backends, + g_strdup (class->backend_name), + g_object_ref (backend)); + } + + g_list_free (list); +} + +static gboolean +mail_config_service_page_backend_to_id (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer user_data) +{ + EMailConfigServiceBackend *backend; + EMailConfigServiceBackendClass *backend_class; + + backend = g_value_get_object (source_value); + g_return_val_if_fail (backend != NULL, FALSE); + + backend_class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + g_value_set_string (target_value, backend_class->backend_name); + + return TRUE; +} + +static gboolean +mail_config_service_page_id_to_backend (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer user_data) +{ + EMailConfigServiceBackend *backend = NULL; + GObject *source_object; + const gchar *backend_name; + + source_object = g_binding_get_source (binding); + backend_name = g_value_get_string (source_value); + + if (backend_name != NULL) + backend = e_mail_config_service_page_lookup_backend ( + E_MAIL_CONFIG_SERVICE_PAGE (source_object), + backend_name); + + g_value_set_object (target_value, backend); + + return TRUE; +} + +static gboolean +mail_config_service_page_backend_name_to_description (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer user_data) +{ + CamelProvider *provider; + const gchar *description; + const gchar *backend_name; + + backend_name = g_value_get_string (source_value); + + /* XXX Silly special case. */ + if (backend_name == NULL) + backend_name = "none"; + + provider = camel_provider_get (backend_name, NULL); + + if (provider != NULL && provider->description != NULL) + description = g_dgettext ( + provider->translation_domain, + provider->description); + else + description = ""; + + g_value_set_string (target_value, description); + + return TRUE; +} + +static Candidate * +mail_config_service_page_get_active_candidate (EMailConfigServicePage *page) +{ + GtkComboBox *combo_box; + gint active; + + combo_box = GTK_COMBO_BOX (page->priv->type_combo); + active = gtk_combo_box_get_active (combo_box); + g_return_val_if_fail (active >= 0, NULL); + + return g_ptr_array_index (page->priv->candidates, active); +} + +static void +mail_config_service_page_set_registry (EMailConfigServicePage *page, + ESourceRegistry *registry) +{ + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_return_if_fail (page->priv->registry == NULL); + + page->priv->registry = g_object_ref (registry); +} + +static void +mail_config_service_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE_BACKEND: + e_mail_config_service_page_set_active_backend ( + E_MAIL_CONFIG_SERVICE_PAGE (object), + g_value_get_object (value)); + return; + + case PROP_EMAIL_ADDRESS: + e_mail_config_service_page_set_email_address ( + E_MAIL_CONFIG_SERVICE_PAGE (object), + g_value_get_string (value)); + return; + + case PROP_REGISTRY: + mail_config_service_page_set_registry ( + E_MAIL_CONFIG_SERVICE_PAGE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_service_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE_BACKEND: + g_value_set_object ( + value, + e_mail_config_service_page_get_active_backend ( + E_MAIL_CONFIG_SERVICE_PAGE (object))); + return; + + case PROP_EMAIL_ADDRESS: + g_value_set_string ( + value, + e_mail_config_service_page_get_email_address ( + E_MAIL_CONFIG_SERVICE_PAGE (object))); + return; + + case PROP_REGISTRY: + g_value_set_object ( + value, + e_mail_config_service_page_get_registry ( + E_MAIL_CONFIG_SERVICE_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_service_page_dispose (GObject *object) +{ + EMailConfigServicePagePrivate *priv; + + priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (object); + + if (priv->registry != NULL) { + g_object_unref (priv->registry); + priv->registry = NULL; + } + + if (priv->active_backend != NULL) { + g_object_unref (priv->active_backend); + priv->active_backend = NULL; + } + + g_hash_table_remove_all (priv->backends); + g_ptr_array_set_size (priv->candidates, 0); + g_ptr_array_set_size (priv->hidden_candidates, 0); + + if (priv->list_store != NULL) { + g_object_unref (priv->list_store); + priv->list_store = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_service_page_parent_class)->dispose (object); +} + +static void +mail_config_service_page_finalize (GObject *object) +{ + EMailConfigServicePagePrivate *priv; + + priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (object); + + g_free (priv->email_address); + g_hash_table_destroy (priv->backends); + g_ptr_array_free (priv->candidates, TRUE); + g_ptr_array_free (priv->hidden_candidates, TRUE); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_service_page_parent_class)->finalize (object); +} + +static void +mail_config_service_page_constructed (GObject *object) +{ + EMailConfigServicePage *page; + + page = E_MAIL_CONFIG_SERVICE_PAGE (object); + + mail_config_service_page_init_backends (page); +} + +static void +mail_config_service_page_submit_alert (EAlertSink *alert_sink, + EAlert *alert) +{ + EMailConfigServicePagePrivate *priv; + EAlertBar *alert_bar; + GtkWidget *dialog; + gpointer parent; + + priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (alert_sink); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (alert_sink)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + switch (e_alert_get_message_type (alert)) { + case GTK_MESSAGE_INFO: + case GTK_MESSAGE_WARNING: + case GTK_MESSAGE_ERROR: + alert_bar = E_ALERT_BAR (priv->alert_bar); + e_alert_bar_add_alert (alert_bar, alert); + break; + + default: + dialog = e_alert_dialog_new (parent, alert); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + break; + } +} + +static void +mail_config_service_page_setup_defaults (EMailConfigPage *page) +{ + EMailConfigServicePageClass *class; + EMailConfigServicePagePrivate *priv; + guint ii; + + class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page); + priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page); + + for (ii = 0; ii < priv->candidates->len; ii++) { + Candidate *candidate; + + candidate = priv->candidates->pdata[ii]; + g_return_if_fail (candidate != NULL); + + e_mail_config_service_backend_setup_defaults ( + candidate->backend); + } + + /* XXX Not sure if we need to call setup_defaults() for + * hidden candidates. Hold off until a need arises. */ + + if (class->default_backend_name != NULL) + gtk_combo_box_set_active_id ( + GTK_COMBO_BOX (priv->type_combo), + class->default_backend_name); +} + +static gboolean +mail_config_service_page_check_complete (EMailConfigPage *page) +{ + EMailConfigServicePagePrivate *priv; + Candidate *candidate; + GtkComboBox *type_combo; + + priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page); + + /* Make sure the combo box has an active item. */ + type_combo = GTK_COMBO_BOX (priv->type_combo); + if (gtk_combo_box_get_active_id (type_combo) == NULL) + return FALSE; + + candidate = mail_config_service_page_get_active_candidate ( + E_MAIL_CONFIG_SERVICE_PAGE (page)); + g_return_val_if_fail (candidate != NULL, FALSE); + + return e_mail_config_service_backend_check_complete ( + candidate->backend); +} + +static void +mail_config_service_page_commit_changes (EMailConfigPage *page, + GQueue *source_queue) +{ + Candidate *candidate; + + candidate = mail_config_service_page_get_active_candidate ( + E_MAIL_CONFIG_SERVICE_PAGE (page)); + g_return_if_fail (candidate != NULL); + + e_mail_config_service_backend_commit_changes (candidate->backend); +} + +static void +e_mail_config_service_page_class_init (EMailConfigServicePageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailConfigServicePagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_service_page_set_property; + object_class->get_property = mail_config_service_page_get_property; + object_class->dispose = mail_config_service_page_dispose; + object_class->finalize = mail_config_service_page_finalize; + object_class->constructed = mail_config_service_page_constructed; + + g_object_class_install_property ( + object_class, + PROP_ACTIVE_BACKEND, + g_param_spec_object ( + "active-backend", + "Active Backend", + "The active service backend", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_EMAIL_ADDRESS, + g_param_spec_string ( + "email-address", + "Email Address", + "The user's email address", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_REGISTRY, + g_param_spec_object ( + "registry", + "Registry", + "Data source registry", + E_TYPE_SOURCE_REGISTRY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_service_page_alert_sink_init (EAlertSinkInterface *interface) +{ + interface->submit_alert = mail_config_service_page_submit_alert; +} + +static void +e_mail_config_service_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->setup_defaults = mail_config_service_page_setup_defaults; + interface->check_complete = mail_config_service_page_check_complete; + interface->commit_changes = mail_config_service_page_commit_changes; +} + +static void +e_mail_config_service_page_init (EMailConfigServicePage *page) +{ + GPtrArray *candidates; + GPtrArray *hidden_candidates; + PangoAttribute *attr; + PangoAttrList *attr_list; + GtkLabel *label; + GtkWidget *frame; + GtkWidget *widget; + GtkWidget *container; + GtkTreeModel *tree_model; + GtkCellRenderer *renderer; + + /* The candidates array holds scratch ESources, one for each + * item in the "type" combo box. Scratch ESources are never + * added to the registry, so backend extensions can make any + * changes they want to them. Whichever scratch ESource is + * "active" (selected in the "type" combo box) when the user + * clicks OK wins and is written to disk. The others are + * discarded. */ + candidates = g_ptr_array_new_with_free_func ( + (GDestroyNotify) mail_config_service_page_free_candidate); + + /* Hidden candidates are not listed in the "type" combo box + * but their scratch ESource can still be "active". This is + * a hack to accommodate groupware backends. Usually when a + * hidden candidate is active the service page will not be + * visible anyway. */ + hidden_candidates = g_ptr_array_new_with_free_func ( + (GDestroyNotify) mail_config_service_page_free_candidate); + + gtk_box_set_spacing (GTK_BOX (page), 12); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + page->priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page); + page->priv->candidates = candidates; + page->priv->hidden_candidates = hidden_candidates; + + /* Build a filtered model for the combo box, where row + * visibility is determined by the "selectable" column. */ + + page->priv->list_store = gtk_list_store_new ( + NUM_COLUMNS, + G_TYPE_STRING, /* COLUMN_BACKEND_NAME */ + G_TYPE_STRING, /* COLUMN_DISPLAY_NAME */ + G_TYPE_BOOLEAN); /* COLUMN_SELECTABLE */ + + tree_model = gtk_tree_model_filter_new ( + GTK_TREE_MODEL (page->priv->list_store), NULL); + + gtk_tree_model_filter_set_visible_column ( + GTK_TREE_MODEL_FILTER (tree_model), COLUMN_SELECTABLE); + + /* Either the combo box or the label is shown, never both. + * But we create both widgets and keep them both up-to-date + * regardless just because it makes the logic simpler. */ + + container = GTK_WIDGET (page); + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 12); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + attr_list = pango_attr_list_new (); + + attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + pango_attr_list_insert (attr_list, attr); + + widget = gtk_label_new_with_mnemonic (_("Server _Type:")); + gtk_widget_set_margin_right (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_combo_box_new_with_model (tree_model); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_combo_box_set_id_column ( + GTK_COMBO_BOX (widget), COLUMN_BACKEND_NAME); + gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 1, 1); + page->priv->type_combo = widget; /* not referenced */ + gtk_widget_show (widget); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start ( + GTK_CELL_LAYOUT (widget), renderer, TRUE); + gtk_cell_layout_add_attribute ( + GTK_CELL_LAYOUT (widget), renderer, + "text", COLUMN_DISPLAY_NAME); + + widget = gtk_label_new (NULL); + gtk_widget_set_hexpand (widget, TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_attributes (GTK_LABEL (widget), attr_list); + gtk_grid_attach (GTK_GRID (container), widget, 2, 0, 1, 1); + page->priv->type_label = widget; /* not referenced */ + gtk_widget_show (widget); + + widget = gtk_label_new (_("Description:")); + gtk_widget_set_margin_right (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.0); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 2, 1); + page->priv->desc_label = widget; /* not referenced */ + gtk_widget_show (widget); + + pango_attr_list_unref (attr_list); + + container = GTK_WIDGET (page); + + widget = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = e_mail_config_service_notebook_new (); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + page->priv->notebook = widget; /* not referenced */ + gtk_widget_show (widget); + + widget = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + /* Visibility is bound to the EActivityBar. */ + + frame = widget; + + widget = e_activity_bar_new (); + gtk_container_add (GTK_CONTAINER (frame), widget); + page->priv->activity_bar = widget; /* not referenced */ + /* EActivityBar controls its own visibility. */ + + g_object_bind_property ( + widget, "visible", + frame, "visible", + G_BINDING_SYNC_CREATE); + + widget = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + /* Visibility is bound to the EAlertBar. */ + + frame = widget; + + widget = e_alert_bar_new (); + gtk_container_add (GTK_CONTAINER (frame), widget); + page->priv->alert_bar = widget; /* not referenced */ + /* EAlertBar controls its own visibility. */ + + g_object_bind_property ( + widget, "visible", + frame, "visible", + G_BINDING_SYNC_CREATE); + + /* Keep the notebook's active page number synchronized with our + * own "active-backend" property. Avoid G_BINDING_SYNC_CREATE + * since we haven't added any notebook pages. */ + g_object_bind_property ( + page, "active-backend", + page->priv->notebook, "active-backend", + G_BINDING_BIDIRECTIONAL); + + /* Keep the combo box's active row number synchronized with our + * own "active-backend" property. Avoid G_BINDING_SYNC_CREATE + * since we haven't added any combo box rows. */ + g_object_bind_property_full ( + page, "active-backend", + page->priv->type_combo, "active-id", + G_BINDING_BIDIRECTIONAL, + mail_config_service_page_backend_to_id, + mail_config_service_page_id_to_backend, + NULL, (GDestroyNotify) NULL); + + /* This keeps the description field up-to-date. */ + g_object_bind_property_full ( + page->priv->type_combo, "active-id", + page->priv->desc_label, "label", + G_BINDING_DEFAULT, + mail_config_service_page_backend_name_to_description, + NULL, + NULL, (GDestroyNotify) NULL); + + /* For the "Server Type", either the combo + * box or the label is visible, never both. */ + g_object_bind_property ( + page->priv->type_combo, "visible", + page->priv->type_label, "visible", + G_BINDING_SYNC_CREATE | + G_BINDING_BIDIRECTIONAL | + G_BINDING_INVERT_BOOLEAN); + + g_signal_connect_swapped ( + page->priv->type_combo, "changed", + G_CALLBACK (e_mail_config_page_changed), page); + + g_object_unref (tree_model); +} + +EMailConfigServiceBackend * +e_mail_config_service_page_get_active_backend (EMailConfigServicePage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL); + + return page->priv->active_backend; +} + +void +e_mail_config_service_page_set_active_backend (EMailConfigServicePage *page, + EMailConfigServiceBackend *backend) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page)); + + if (backend != NULL) { + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + g_object_ref (backend); + } + + if (page->priv->active_backend != NULL) + g_object_unref (page->priv->active_backend); + + page->priv->active_backend = backend; + + g_object_notify (G_OBJECT (page), "active-backend"); +} + +const gchar * +e_mail_config_service_page_get_email_address (EMailConfigServicePage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL); + + return page->priv->email_address; +} + +void +e_mail_config_service_page_set_email_address (EMailConfigServicePage *page, + const gchar *email_address) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page)); + + g_free (page->priv->email_address); + page->priv->email_address = g_strdup (email_address); + + g_object_notify (G_OBJECT (page), "email-address"); +} + +ESourceRegistry * +e_mail_config_service_page_get_registry (EMailConfigServicePage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL); + + return page->priv->registry; +} + +EMailConfigServiceBackend * +e_mail_config_service_page_add_scratch_source (EMailConfigServicePage *page, + ESource *scratch_source, + ESource *opt_collection) +{ + GtkWidget *widget; + GtkLabel *type_label; + GtkComboBox *type_combo; + GtkTreeIter iter; + Candidate *candidate; + const gchar *display_name; + gboolean selectable; + gint page_num; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL); + g_return_val_if_fail (E_IS_SOURCE (scratch_source), NULL); + + if (opt_collection != NULL) + g_return_val_if_fail (E_IS_SOURCE (opt_collection), NULL); + + type_label = GTK_LABEL (page->priv->type_label); + type_combo = GTK_COMBO_BOX (page->priv->type_combo); + + candidate = mail_config_service_page_new_candidate ( + page, scratch_source, opt_collection); + g_return_val_if_fail (candidate != NULL, NULL); + + widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + e_mail_config_service_backend_insert_widgets ( + candidate->backend, GTK_BOX (widget)); + candidate->widget = g_object_ref_sink (widget); + gtk_widget_show (widget); + + g_ptr_array_add (page->priv->candidates, candidate); + + display_name = g_dgettext ( + candidate->provider->translation_domain, + candidate->provider->name); + + page_num = e_mail_config_service_notebook_add_page ( + E_MAIL_CONFIG_SERVICE_NOTEBOOK (page->priv->notebook), + candidate->backend, widget); + + selectable = e_mail_config_service_backend_get_selectable ( + candidate->backend); + + gtk_list_store_append (page->priv->list_store, &iter); + + gtk_list_store_set ( + page->priv->list_store, &iter, + COLUMN_BACKEND_NAME, candidate->name, + COLUMN_DISPLAY_NAME, display_name, + COLUMN_SELECTABLE, selectable, + -1); + + /* The type label is only visible if we have one scratch source, + * so just always set the label text to the most recently added + * scratch source. */ + gtk_label_set_text (type_label, display_name); + + /* If no combo box row is active yet, choose the new row. */ + if (gtk_combo_box_get_active_id (type_combo) == NULL) + gtk_combo_box_set_active_id (type_combo, candidate->name); + + /* If the page number of the newly-added notebook page is zero, + * show the "type" label. Otherwise show the "type" combo box. + * There's an inverted "visible" binding between the combo box + * and label, so we only need to change one of the widgets. */ + gtk_widget_set_visible (GTK_WIDGET (type_combo), page_num > 0); + + return candidate->backend; +} + +EMailConfigServiceBackend * +e_mail_config_service_page_lookup_backend (EMailConfigServicePage *page, + const gchar *backend_name) +{ + guint index; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL); + g_return_val_if_fail (backend_name != NULL, NULL); + + for (index = 0; index < page->priv->candidates->len; index++) { + Candidate *candidate; + + candidate = page->priv->candidates->pdata[index]; + + if (g_strcmp0 (backend_name, candidate->name) == 0) + return candidate->backend; + } + + return NULL; +} + +EActivity * +e_mail_config_service_page_new_activity (EMailConfigServicePage *page) +{ + EActivity *activity; + EActivityBar *activity_bar; + GCancellable *cancellable; + + g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL); + + /* Clear any previous alerts. */ + e_alert_bar_clear (E_ALERT_BAR (page->priv->alert_bar)); + + activity = e_activity_new (); + + e_activity_set_alert_sink (activity, E_ALERT_SINK (page)); + + cancellable = camel_operation_new (); + e_activity_set_cancellable (activity, cancellable); + g_object_unref (cancellable); + + activity_bar = E_ACTIVITY_BAR (page->priv->activity_bar); + e_activity_bar_set_activity (activity_bar, activity); + + return activity; +} + +void +e_mail_config_service_page_auto_configure (EMailConfigServicePage *page, + EMailAutoconfig *autoconfig) +{ + EMailConfigServiceBackend *pop3 = NULL; + EMailConfigServiceBackend *imap = NULL; + EMailConfigServiceBackend *smtp = NULL; + guint ii; + + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page)); + g_return_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig)); + + for (ii = 0; ii < page->priv->candidates->len; ii++) { + EMailConfigServiceBackendClass *class; + EMailConfigServiceBackend *backend; + Candidate *candidate; + gboolean configured; + + candidate = page->priv->candidates->pdata[ii]; + + backend = candidate->backend; + class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend); + + configured = e_mail_config_service_backend_auto_configure ( + backend, autoconfig); + + /* XXX There's a few specific backends to check for. + * It requires that we know about these backends, + * which violates the abstraction, but we need to + * break our own rule to be practical here. */ + if (g_strcmp0 (class->backend_name, POP3_BACKEND_NAME) == 0) + pop3 = configured ? backend : NULL; + if (g_strcmp0 (class->backend_name, IMAP_BACKEND_NAME) == 0) + imap = configured ? backend : NULL; + if (g_strcmp0 (class->backend_name, SMTP_BACKEND_NAME) == 0) + smtp = configured ? backend : NULL; + } + + /* Select POP3 before IMAP. If both are present we want IMAP. */ + if (pop3 != NULL) + e_mail_config_service_page_set_active_backend (page, pop3); + if (imap != NULL) + e_mail_config_service_page_set_active_backend (page, imap); + if (smtp != NULL) + e_mail_config_service_page_set_active_backend (page, smtp); +} + diff --git a/mail/e-mail-config-service-page.h b/mail/e-mail-config-service-page.h new file mode 100644 index 0000000000..3c5a40e1c0 --- /dev/null +++ b/mail/e-mail-config-service-page.h @@ -0,0 +1,107 @@ +/* + * e-mail-config-service-page.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/> + * + */ + +/* XXX This is very similar to ESourceConfig for address books and + * calendars, but not similar enough to easily unify the APIs. + * Probably with more thought and effort it could be done. */ + +#ifndef E_MAIL_CONFIG_SERVICE_PAGE_H +#define E_MAIL_CONFIG_SERVICE_PAGE_H + +#include <gtk/gtk.h> +#include <camel/camel.h> +#include <libedataserver/e-source-extension.h> +#include <libedataserver/e-source-registry.h> + +#include <e-util/e-activity.h> +#include <mail/e-mail-autoconfig.h> +#include <mail/e-mail-config-service-backend.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_SERVICE_PAGE \ + (e_mail_config_service_page_get_type ()) +#define E_MAIL_CONFIG_SERVICE_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePage)) +#define E_MAIL_CONFIG_SERVICE_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePageClass)) +#define E_IS_MAIL_CONFIG_SERVICE_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE)) +#define E_IS_MAIL_CONFIG_SERVICE_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_SERVICE_PAGE)) +#define E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePageClass)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigServicePage EMailConfigServicePage; +typedef struct _EMailConfigServicePageClass EMailConfigServicePageClass; +typedef struct _EMailConfigServicePagePrivate EMailConfigServicePagePrivate; + +struct _EMailConfigServicePage { + GtkBox parent; + EMailConfigServicePagePrivate *priv; +}; + +struct _EMailConfigServicePageClass { + GtkBoxClass parent_class; + + const gchar *extension_name; + CamelProviderType provider_type; + const gchar *default_backend_name; +}; + +GType e_mail_config_service_page_get_type + (void) G_GNUC_CONST; +EMailConfigServiceBackend * + e_mail_config_service_page_get_active_backend + (EMailConfigServicePage *page); +void e_mail_config_service_page_set_active_backend + (EMailConfigServicePage *page, + EMailConfigServiceBackend *backend); +const gchar * e_mail_config_service_page_get_email_address + (EMailConfigServicePage *page); +void e_mail_config_service_page_set_email_address + (EMailConfigServicePage *page, + const gchar *email_address); +ESourceRegistry * + e_mail_config_service_page_get_registry + (EMailConfigServicePage *page); +EMailConfigServiceBackend * + e_mail_config_service_page_add_scratch_source + (EMailConfigServicePage *page, + ESource *scratch_source, + ESource *opt_collection); +EMailConfigServiceBackend * + e_mail_config_service_page_lookup_backend + (EMailConfigServicePage *page, + const gchar *backend_name); +EActivity * e_mail_config_service_page_new_activity + (EMailConfigServicePage *page); +void e_mail_config_service_page_auto_configure + (EMailConfigServicePage *page, + EMailAutoconfig *autoconfig); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_SERVICE_PAGE_H */ + diff --git a/mail/e-mail-config-sidebar.c b/mail/e-mail-config-sidebar.c new file mode 100644 index 0000000000..91d2dbaf81 --- /dev/null +++ b/mail/e-mail-config-sidebar.c @@ -0,0 +1,416 @@ +/* + * e-mail-config-sidebar.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-config-sidebar.h" + +#define E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebarPrivate)) + +struct _EMailConfigSidebarPrivate { + EMailConfigNotebook *notebook; + gint active; + + GHashTable *buttons_to_pages; + GHashTable *pages_to_buttons; + + gulong page_added_handler_id; + gulong page_removed_handler_id; + gulong page_reordered_handler_id; +}; + +enum { + PROP_0, + PROP_ACTIVE, + PROP_NOTEBOOK +}; + +G_DEFINE_TYPE ( + EMailConfigSidebar, + e_mail_config_sidebar, + GTK_TYPE_BUTTON_BOX) + +static void +mail_config_sidebar_button_toggled (GtkToggleButton *button, + EMailConfigSidebar *sidebar) +{ + if (gtk_toggle_button_get_active (button)) { + GHashTable *hash_table; + GtkNotebook *notebook; + GtkWidget *page; + gint page_num; + + hash_table = sidebar->priv->buttons_to_pages; + page = g_hash_table_lookup (hash_table, button); + g_return_if_fail (GTK_IS_WIDGET (page)); + + notebook = GTK_NOTEBOOK (sidebar->priv->notebook); + page_num = gtk_notebook_page_num (notebook, page); + e_mail_config_sidebar_set_active (sidebar, page_num); + } +} + +static void +mail_config_sidebar_notebook_page_added (GtkNotebook *notebook, + GtkWidget *page, + guint page_num, + EMailConfigSidebar *sidebar) +{ + GtkRadioButton *group_member; + GtkWidget *button; + GList *keys; + gchar *tab_label = NULL; + + /* Grab another radio button if we have any. */ + keys = g_hash_table_get_keys (sidebar->priv->buttons_to_pages); + group_member = (keys != NULL) ? GTK_RADIO_BUTTON (keys->data) : NULL; + g_list_free (keys); + + gtk_container_child_get ( + GTK_CONTAINER (notebook), page, + "tab-label", &tab_label, NULL); + + button = gtk_radio_button_new_with_label_from_widget ( + group_member, tab_label); + g_object_set (button, "draw-indicator", FALSE, NULL); + gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); + gtk_box_pack_start (GTK_BOX (sidebar), button, FALSE, FALSE, 0); + gtk_box_reorder_child (GTK_BOX (sidebar), button, page_num); + gtk_widget_show (button); + + g_signal_connect ( + button, "toggled", + G_CALLBACK (mail_config_sidebar_button_toggled), sidebar); + + g_hash_table_insert ( + sidebar->priv->pages_to_buttons, + g_object_ref (page), g_object_ref (button)); + + g_hash_table_insert ( + sidebar->priv->buttons_to_pages, + g_object_ref (button), g_object_ref (page)); +} + +static void +mail_config_sidebar_notebook_page_removed (GtkNotebook *notebook, + GtkWidget *page, + guint page_num, + EMailConfigSidebar *sidebar) +{ + GHashTable *hash_table; + GtkWidget *button; + + hash_table = sidebar->priv->pages_to_buttons; + button = g_hash_table_lookup (hash_table, page); + g_return_if_fail (GTK_IS_WIDGET (button)); + + gtk_container_remove (GTK_CONTAINER (sidebar), button); + + g_hash_table_remove (sidebar->priv->pages_to_buttons, page); + g_hash_table_remove (sidebar->priv->buttons_to_pages, button); +} + +static void +mail_config_sidebar_notebook_page_reordered (GtkNotebook *notebook, + GtkWidget *page, + guint page_num, + EMailConfigSidebar *sidebar) +{ + GHashTable *hash_table; + GtkWidget *button; + + hash_table = sidebar->priv->pages_to_buttons; + button = g_hash_table_lookup (hash_table, page); + g_return_if_fail (GTK_IS_WIDGET (button)); + + gtk_box_reorder_child (GTK_BOX (sidebar), button, page_num); +} + +static void +mail_config_sidebar_set_notebook (EMailConfigSidebar *sidebar, + EMailConfigNotebook *notebook) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook)); + g_return_if_fail (sidebar->priv->notebook == NULL); + + sidebar->priv->notebook = g_object_ref (notebook); +} + +static void +mail_config_sidebar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE: + e_mail_config_sidebar_set_active ( + E_MAIL_CONFIG_SIDEBAR (object), + g_value_get_int (value)); + return; + + case PROP_NOTEBOOK: + mail_config_sidebar_set_notebook ( + E_MAIL_CONFIG_SIDEBAR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTIVE: + g_value_set_int ( + value, + e_mail_config_sidebar_get_active ( + E_MAIL_CONFIG_SIDEBAR (object))); + return; + + case PROP_NOTEBOOK: + g_value_set_object ( + value, + e_mail_config_sidebar_get_notebook ( + E_MAIL_CONFIG_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_sidebar_dispose (GObject *object) +{ + EMailConfigSidebarPrivate *priv; + + priv = E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE (object); + + if (priv->notebook != NULL) { + g_signal_handler_disconnect ( + priv->notebook, priv->page_added_handler_id); + g_signal_handler_disconnect ( + priv->notebook, priv->page_removed_handler_id); + g_signal_handler_disconnect ( + priv->notebook, priv->page_reordered_handler_id); + g_object_unref (priv->notebook); + priv->notebook = NULL; + } + + g_hash_table_remove_all (priv->buttons_to_pages); + g_hash_table_remove_all (priv->pages_to_buttons); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_sidebar_parent_class)->dispose (object); +} + +static void +mail_config_sidebar_finalize (GObject *object) +{ + EMailConfigSidebarPrivate *priv; + + priv = E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->buttons_to_pages); + g_hash_table_destroy (priv->pages_to_buttons); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_sidebar_parent_class)->finalize (object); +} + +static void +mail_config_sidebar_constructed (GObject *object) +{ + EMailConfigSidebar *sidebar; + GtkNotebook *notebook; + gulong handler_id; + gint n_pages, ii; + + sidebar = E_MAIL_CONFIG_SIDEBAR (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_sidebar_parent_class)-> + constructed (object); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (sidebar), GTK_ORIENTATION_VERTICAL); + + gtk_button_box_set_layout ( + GTK_BUTTON_BOX (sidebar), GTK_BUTTONBOX_START); + + gtk_box_set_homogeneous (GTK_BOX (sidebar), TRUE); + gtk_box_set_spacing (GTK_BOX (sidebar), 6); + + /* Add buttons for existing notebook pages before + * binding to properties or connecting to signals. */ + + notebook = GTK_NOTEBOOK (sidebar->priv->notebook); + n_pages = gtk_notebook_get_n_pages (notebook); + + for (ii = 0; ii < n_pages; ii++) { + GtkWidget *page; + + page = gtk_notebook_get_nth_page (notebook, ii); + mail_config_sidebar_notebook_page_added ( + notebook, page, (guint) ii, sidebar); + } + + g_object_bind_property ( + sidebar, "active", + notebook, "page", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + handler_id = g_signal_connect ( + notebook, "page-added", + G_CALLBACK (mail_config_sidebar_notebook_page_added), + sidebar); + sidebar->priv->page_added_handler_id = handler_id; + + handler_id = g_signal_connect ( + notebook, "page-removed", + G_CALLBACK (mail_config_sidebar_notebook_page_removed), + sidebar); + sidebar->priv->page_removed_handler_id = handler_id; + + handler_id = g_signal_connect ( + notebook, "page-reordered", + G_CALLBACK (mail_config_sidebar_notebook_page_reordered), + sidebar); + sidebar->priv->page_reordered_handler_id = handler_id; +} + +static void +e_mail_config_sidebar_class_init (EMailConfigSidebarClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailConfigSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_sidebar_set_property; + object_class->get_property = mail_config_sidebar_get_property; + object_class->dispose = mail_config_sidebar_dispose; + object_class->finalize = mail_config_sidebar_finalize; + object_class->constructed = mail_config_sidebar_constructed; + + /* Use the same constraints as GtkNotebook:page. */ + g_object_class_install_property ( + object_class, + PROP_ACTIVE, + g_param_spec_int ( + "active", + "Active", + "Index of the currently active button", + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_NOTEBOOK, + g_param_spec_object ( + "notebook", + "Notebook", + "Mail configuration notebook", + E_TYPE_MAIL_CONFIG_NOTEBOOK, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_sidebar_init (EMailConfigSidebar *sidebar) +{ + GHashTable *buttons_to_pages; + GHashTable *pages_to_buttons; + + buttons_to_pages = g_hash_table_new_full ( + (GHashFunc) g_direct_hash, + (GEqualFunc) g_direct_equal, + (GDestroyNotify) g_object_unref, + (GDestroyNotify) g_object_unref); + + pages_to_buttons = g_hash_table_new_full ( + (GHashFunc) g_direct_hash, + (GEqualFunc) g_direct_equal, + (GDestroyNotify) g_object_unref, + (GDestroyNotify) g_object_unref); + + sidebar->priv = E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE (sidebar); + sidebar->priv->buttons_to_pages = buttons_to_pages; + sidebar->priv->pages_to_buttons = pages_to_buttons; +} + +GtkWidget * +e_mail_config_sidebar_new (EMailConfigNotebook *notebook) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_SIDEBAR, + "notebook", notebook, NULL); +} + +gint +e_mail_config_sidebar_get_active (EMailConfigSidebar *sidebar) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SIDEBAR (sidebar), -1); + + return sidebar->priv->active; +} + +void +e_mail_config_sidebar_set_active (EMailConfigSidebar *sidebar, + gint active) +{ + GtkNotebook *notebook; + GtkWidget *page; + + g_return_if_fail (E_IS_MAIL_CONFIG_SIDEBAR (sidebar)); + + notebook = GTK_NOTEBOOK (sidebar->priv->notebook); + page = gtk_notebook_get_nth_page (notebook, active); + + sidebar->priv->active = (page != NULL) ? active : -1; + + g_object_notify (G_OBJECT (sidebar), "active"); + + if (page != NULL) { + GHashTable *hash_table; + GtkToggleButton *button; + + hash_table = sidebar->priv->pages_to_buttons; + button = g_hash_table_lookup (hash_table, page); + gtk_toggle_button_set_active (button, TRUE); + } +} + +EMailConfigNotebook * +e_mail_config_sidebar_get_notebook (EMailConfigSidebar *sidebar) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SIDEBAR (sidebar), NULL); + + return sidebar->priv->notebook; +} + diff --git a/mail/e-mail-config-sidebar.h b/mail/e-mail-config-sidebar.h new file mode 100644 index 0000000000..50f272ef4e --- /dev/null +++ b/mail/e-mail-config-sidebar.h @@ -0,0 +1,72 @@ +/* + * e-mail-config-sidebar.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_CONFIG_SIDEBAR_H +#define E_MAIL_CONFIG_SIDEBAR_H + +#include <mail/e-mail-config-notebook.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_SIDEBAR \ + (e_mail_config_sidebar_get_type ()) +#define E_MAIL_CONFIG_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebar)) +#define E_MAIL_CONFIG_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebarClass)) +#define E_IS_MAIL_CONFIG_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_SIDEBAR)) +#define E_IS_MAIL_CONFIG_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_SIDEBAR)) +#define E_MAIL_CONFIG_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigSidebar EMailConfigSidebar; +typedef struct _EMailConfigSidebarClass EMailConfigSidebarClass; +typedef struct _EMailConfigSidebarPrivate EMailConfigSidebarPrivate; + +struct _EMailConfigSidebar { + GtkButtonBox parent; + EMailConfigSidebarPrivate *priv; +}; + +struct _EMailConfigSidebarClass { + GtkButtonBoxClass parent_class; +}; + +GType e_mail_config_sidebar_get_type (void) G_GNUC_CONST; +GtkWidget * e_mail_config_sidebar_new (EMailConfigNotebook *notebook); +gint e_mail_config_sidebar_get_active + (EMailConfigSidebar *sidebar); +void e_mail_config_sidebar_set_active + (EMailConfigSidebar *sidebar, + gint active); +EMailConfigNotebook * + e_mail_config_sidebar_get_notebook + (EMailConfigSidebar *sidebar); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_SIDEBAR_H */ + diff --git a/mail/e-mail-config-summary-page.c b/mail/e-mail-config-summary-page.c new file mode 100644 index 0000000000..db6520ab1f --- /dev/null +++ b/mail/e-mail-config-summary-page.c @@ -0,0 +1,1064 @@ +/* + * e-mail-config-summary-page.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-config-summary-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <camel/camel.h> + +#include <libebackend/e-extensible.h> +#include <libedataserver/e-source-authentication.h> +#include <libedataserver/e-source-collection.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-identity.h> +#include <libedataserver/e-source-mail-submission.h> +#include <libedataserver/e-source-mail-transport.h> +#include <libedataserver/e-source-security.h> + +#define E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPagePrivate)) + +struct _EMailConfigSummaryPagePrivate { + gchar *account_name; + ESource *account_source; + ESource *identity_source; + ESource *transport_source; + EMailConfigServiceBackend *account_backend; + EMailConfigServiceBackend *transport_backend; + + gulong account_source_changed_id; + gulong identity_source_changed_id; + gulong transport_source_changed_id; + + /* Widgets (not referenced) */ + GtkLabel *name_label; + GtkLabel *address_label; + GtkLabel *recv_backend_label; + GtkLabel *recv_host_label; + GtkLabel *recv_user_label; + GtkLabel *recv_security_label; + GtkLabel *send_backend_label; + GtkLabel *send_host_label; + GtkLabel *send_user_label; + GtkLabel *send_security_label; + GtkEntry *account_name_entry; +}; + +enum { + PROP_0, + PROP_ACCOUNT_NAME, + PROP_ACCOUNT_BACKEND, + PROP_ACCOUNT_SOURCE, + PROP_IDENTITY_SOURCE, + PROP_TRANSPORT_BACKEND, + PROP_TRANSPORT_SOURCE +}; + +enum { + REFRESH, + LAST_SIGNAL +}; + +static gulong signals[LAST_SIGNAL]; + +/* Forward Declarations */ +static void e_mail_config_summary_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigSummaryPage, + e_mail_config_summary_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_summary_page_interface_init)) + +/* Helper for mail_config_summary_page_refresh() */ +static void +mail_config_summary_page_refresh_auth_labels (ESource *source, + GtkLabel *host_label, + GtkLabel *user_label) +{ + ESourceAuthentication *extension; + const gchar *extension_name; + const gchar *value; + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + if (!e_source_has_extension (source, extension_name)) + return; + + extension = e_source_get_extension (source, extension_name); + + value = e_source_authentication_get_host (extension); + gtk_label_set_text (host_label, value); + + value = e_source_authentication_get_user (extension); + gtk_label_set_text (user_label, value); +} + +/* Helper for mail_config_summary_page_refresh() */ +static void +mail_config_summary_page_refresh_security_label (ESource *source, + GtkLabel *security_label) +{ + GEnumClass *enum_class; + GEnumValue *enum_value; + ESourceSecurity *extension; + const gchar *extension_name; + const gchar *value; + + extension_name = E_SOURCE_EXTENSION_SECURITY; + if (!e_source_has_extension (source, extension_name)) + return; + + extension = e_source_get_extension (source, extension_name); + + /* XXX This is a pain in the butt, but we want to avoid hard-coding + * string values from the CamelNetworkSecurityMethod enum class + * in case they change in the future. */ + enum_class = g_type_class_ref (CAMEL_TYPE_NETWORK_SECURITY_METHOD); + value = e_source_security_get_method (extension); + if (value != NULL) + enum_value = g_enum_get_value_by_nick (enum_class, value); + else + enum_value = NULL; + if (enum_value == NULL) { + gtk_label_set_text (security_label, value); + } else switch ((CamelNetworkSecurityMethod) enum_value->value) { + case CAMEL_NETWORK_SECURITY_METHOD_NONE: + gtk_label_set_text (security_label, _("None")); + break; + case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT: + gtk_label_set_text (security_label, _("SSL")); + break; + case CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT: + gtk_label_set_text (security_label, _("TLS")); + break; + } + g_type_class_unref (enum_class); +} + +static void +mail_config_summary_page_source_changed (ESource *source, + EMailConfigSummaryPage *page) +{ + e_mail_config_summary_page_refresh (page); +} + +static void +mail_config_summary_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_NAME: + e_mail_config_summary_page_set_account_name ( + E_MAIL_CONFIG_SUMMARY_PAGE (object), + g_value_get_string (value)); + return; + + case PROP_ACCOUNT_BACKEND: + e_mail_config_summary_page_set_account_backend ( + E_MAIL_CONFIG_SUMMARY_PAGE (object), + g_value_get_object (value)); + return; + + case PROP_IDENTITY_SOURCE: + e_mail_config_summary_page_set_identity_source ( + E_MAIL_CONFIG_SUMMARY_PAGE (object), + g_value_get_object (value)); + return; + + case PROP_TRANSPORT_BACKEND: + e_mail_config_summary_page_set_transport_backend ( + E_MAIL_CONFIG_SUMMARY_PAGE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_summary_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_NAME: + g_value_set_string ( + value, + e_mail_config_summary_page_get_account_name ( + E_MAIL_CONFIG_SUMMARY_PAGE (object))); + return; + + case PROP_ACCOUNT_BACKEND: + g_value_set_object ( + value, + e_mail_config_summary_page_get_account_backend ( + E_MAIL_CONFIG_SUMMARY_PAGE (object))); + return; + + case PROP_ACCOUNT_SOURCE: + g_value_set_object ( + value, + e_mail_config_summary_page_get_account_source ( + E_MAIL_CONFIG_SUMMARY_PAGE (object))); + return; + + case PROP_IDENTITY_SOURCE: + g_value_set_object ( + value, + e_mail_config_summary_page_get_identity_source ( + E_MAIL_CONFIG_SUMMARY_PAGE (object))); + return; + + case PROP_TRANSPORT_BACKEND: + g_value_set_object ( + value, + e_mail_config_summary_page_get_transport_backend ( + E_MAIL_CONFIG_SUMMARY_PAGE (object))); + return; + + case PROP_TRANSPORT_SOURCE: + g_value_set_object ( + value, + e_mail_config_summary_page_get_transport_source ( + E_MAIL_CONFIG_SUMMARY_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_summary_page_dispose (GObject *object) +{ + EMailConfigSummaryPagePrivate *priv; + + priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (object); + + if (priv->account_source != NULL) { + g_signal_handler_disconnect ( + priv->account_source, + priv->account_source_changed_id); + g_object_unref (priv->account_source); + priv->account_source = NULL; + priv->account_source_changed_id = 0; + } + + if (priv->identity_source != NULL) { + g_signal_handler_disconnect ( + priv->identity_source, + priv->identity_source_changed_id); + g_object_unref (priv->identity_source); + priv->identity_source = NULL; + } + + if (priv->transport_source != NULL) { + g_signal_handler_disconnect ( + priv->transport_source, + priv->transport_source_changed_id); + g_object_unref (priv->transport_source); + priv->transport_source = NULL; + priv->transport_source_changed_id = 0; + } + + if (priv->account_backend != NULL) { + g_object_unref (priv->account_backend); + priv->account_backend = NULL; + } + + if (priv->transport_backend != NULL) { + g_object_unref (priv->transport_backend); + priv->transport_backend = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_summary_page_parent_class)-> + dispose (object); +} + +static void +mail_config_summary_page_finalize (GObject *object) +{ + EMailConfigSummaryPagePrivate *priv; + + priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (object); + + g_free (priv->account_name); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_summary_page_parent_class)-> + finalize (object); +} + +static void +mail_config_summary_page_constructed (GObject *object) +{ + EMailConfigSummaryPage *page; + GtkLabel *label; + GtkWidget *widget; + GtkWidget *container; + GtkSizeGroup *size_group; + const gchar *text; + gchar *markup; + + page = E_MAIL_CONFIG_SUMMARY_PAGE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_summary_page_parent_class)-> + constructed (object); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + /* This page is dense with information, + * so put extra space between sections. */ + gtk_box_set_spacing (GTK_BOX (page), 24); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + text = _("This is a summary of the settings which will be used " + "to access your mail."); + widget = gtk_label_new (text); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + /*** Account Information ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Account Information"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Type the name by which you would like to refer to " + "this account.\nFor example, \"Work\" or \"Personal\"."); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 2, 1); + gtk_widget_show (widget); + + text = _("_Name:"); + widget = gtk_label_new_with_mnemonic (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_widget_set_hexpand (widget, TRUE); + gtk_label_set_mnemonic_widget (label, widget); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1); + page->priv->account_name_entry = GTK_ENTRY (widget); + gtk_widget_show (widget); + + /* This entry affects the "check-complete" result. */ + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (e_mail_config_page_changed), page); + + g_object_bind_property ( + widget, "text", + page, "account-name", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + /*** Details ***/ + + widget = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (widget), 6); + gtk_grid_set_column_spacing (GTK_GRID (widget), 12); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + text = _("Personal Details"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 3, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Full Name:"); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 2, 1); + page->priv->name_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + text = _("Email Address:"); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 2, 1); + page->priv->address_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + text = _("Receiving"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_margin_top (widget, 6); + gtk_size_group_add_widget (size_group, widget); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 1, 3, 1, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Sending"); + markup = g_markup_printf_escaped ("<b>%s</b>", text); + widget = gtk_label_new (markup); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_margin_top (widget, 6); + gtk_size_group_add_widget (size_group, widget); + gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 2, 3, 1, 1); + gtk_widget_show (widget); + g_free (markup); + + text = _("Server Type:"); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 1, 4, 1, 1); + page->priv->recv_backend_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 2, 4, 1, 1); + page->priv->send_backend_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + text = _("Server:"); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 1, 1); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 1, 5, 1, 1); + page->priv->recv_host_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 2, 5, 1, 1); + page->priv->send_host_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + text = _("Username:"); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 6, 1, 1); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 1, 6, 1, 1); + page->priv->recv_user_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 2, 6, 1, 1); + page->priv->send_user_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + text = _("Security:"); + widget = gtk_label_new (text); + gtk_widget_set_margin_left (widget, 12); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_grid_attach (GTK_GRID (container), widget, 0, 7, 1, 1); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 1, 7, 1, 1); + page->priv->recv_security_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_grid_attach (GTK_GRID (container), widget, 2, 7, 1, 1); + page->priv->send_security_label = GTK_LABEL (widget); + gtk_widget_show (widget); + + g_object_unref (size_group); + + e_extensible_load_extensions (E_EXTENSIBLE (page)); +} + +static void +mail_config_summary_page_refresh (EMailConfigSummaryPage *page) +{ + EMailConfigSummaryPagePrivate *priv; + ESource *source; + gboolean account_is_transport = FALSE; + + priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page); + + /* Clear all labels. */ + gtk_label_set_text (priv->name_label, ""); + gtk_label_set_text (priv->address_label, ""); + gtk_label_set_text (priv->recv_backend_label, ""); + gtk_label_set_text (priv->recv_host_label, ""); + gtk_label_set_text (priv->recv_user_label, ""); + gtk_label_set_text (priv->recv_security_label, ""); + gtk_label_set_text (priv->send_backend_label, ""); + gtk_label_set_text (priv->send_host_label, ""); + gtk_label_set_text (priv->send_user_label, ""); + gtk_label_set_text (priv->send_security_label, ""); + + source = e_mail_config_summary_page_get_identity_source (page); + + if (source != NULL) { + ESourceMailIdentity *extension; + const gchar *extension_name; + const gchar *value; + + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + extension = e_source_get_extension (source, extension_name); + + value = e_source_mail_identity_get_name (extension); + gtk_label_set_text (priv->name_label, value); + + value = e_source_mail_identity_get_address (extension); + gtk_label_set_text (priv->address_label, value); + } + + source = e_mail_config_summary_page_get_account_source (page); + + if (source != NULL) { + ESourceBackend *extension; + const gchar *extension_name; + const gchar *value; + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + extension = e_source_get_extension (source, extension_name); + + value = e_source_backend_get_backend_name (extension); + gtk_label_set_text (priv->recv_backend_label, value); + + mail_config_summary_page_refresh_auth_labels ( + source, + priv->recv_host_label, + priv->recv_user_label); + + mail_config_summary_page_refresh_security_label ( + source, + priv->recv_security_label); + + extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; + if (e_source_has_extension (source, extension_name)) + account_is_transport = TRUE; + } + + if (account_is_transport) + source = e_mail_config_summary_page_get_account_source (page); + else + source = e_mail_config_summary_page_get_transport_source (page); + + if (source != NULL) { + ESourceBackend *extension; + const gchar *extension_name; + const gchar *value; + + extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; + extension = e_source_get_extension (source, extension_name); + + value = e_source_backend_get_backend_name (extension); + gtk_label_set_text (priv->send_backend_label, value); + + mail_config_summary_page_refresh_auth_labels ( + source, + priv->send_host_label, + priv->send_user_label); + + mail_config_summary_page_refresh_security_label ( + source, + priv->send_security_label); + } +} + +static gboolean +mail_config_summary_page_check_complete (EMailConfigPage *page) +{ + EMailConfigSummaryPagePrivate *priv; + gchar *stripped_text; + const gchar *text; + gboolean complete; + + priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page); + + /* Strip the account name of leading and trailing + * whitespace as e_source_set_display_name() does. */ + text = gtk_entry_get_text (priv->account_name_entry); + stripped_text = g_strstrip (g_strdup ((text != NULL) ? text : "")); + complete = (*stripped_text != '\0'); + g_free (stripped_text); + + return complete; +} + +static void +mail_config_summary_page_commit_changes (EMailConfigPage *page, + GQueue *source_queue) +{ + EMailConfigSummaryPagePrivate *priv; + EMailConfigServiceBackend *backend; + ESource *account_source; + ESource *identity_source; + ESource *transport_source; + ESource *collection_source; + ESourceExtension *extension; + const gchar *extension_name; + const gchar *parent_uid; + const gchar *text; + + priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page); + + backend = e_mail_config_summary_page_get_account_backend ( + E_MAIL_CONFIG_SUMMARY_PAGE (page)); + account_source = + e_mail_config_service_backend_get_source (backend); + collection_source = + e_mail_config_service_backend_get_collection (backend); + + /* The transport backend is NULL when the Sending Page is hidden. */ + backend = e_mail_config_summary_page_get_transport_backend ( + E_MAIL_CONFIG_SUMMARY_PAGE (page)); + transport_source = (backend != NULL) ? + e_mail_config_service_backend_get_source (backend) : NULL; + + identity_source = e_mail_config_summary_page_get_identity_source ( + E_MAIL_CONFIG_SUMMARY_PAGE (page)); + + text = gtk_entry_get_text (priv->account_name_entry); + e_source_set_display_name (account_source, text); + e_source_set_display_name (identity_source, text); + if (transport_source != NULL) + e_source_set_display_name (transport_source, text); + if (collection_source != NULL) + e_source_set_display_name (collection_source, text); + + /* Setup parent/child relationships and cross-references. */ + + if (collection_source != NULL) { + parent_uid = e_source_get_uid (collection_source); + e_source_set_parent (account_source, parent_uid); + e_source_set_parent (identity_source, parent_uid); + if (transport_source != NULL) + e_source_set_parent (transport_source, parent_uid); + } else { + parent_uid = e_source_get_uid (account_source); + e_source_set_parent (identity_source, parent_uid); + if (transport_source != NULL) + e_source_set_parent (transport_source, parent_uid); + } + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + extension = e_source_get_extension (account_source, extension_name); + e_source_mail_account_set_identity_uid ( + E_SOURCE_MAIL_ACCOUNT (extension), + e_source_get_uid (identity_source)); + + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + extension = e_source_get_extension (identity_source, extension_name); + if (transport_source != NULL) + e_source_mail_submission_set_transport_uid ( + E_SOURCE_MAIL_SUBMISSION (extension), + e_source_get_uid (transport_source)); +} + +static void +e_mail_config_summary_page_class_init (EMailConfigSummaryPageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigSummaryPagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_summary_page_set_property; + object_class->get_property = mail_config_summary_page_get_property; + object_class->dispose = mail_config_summary_page_dispose; + object_class->finalize = mail_config_summary_page_finalize; + object_class->constructed = mail_config_summary_page_constructed; + + class->refresh = mail_config_summary_page_refresh; + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT_NAME, + g_param_spec_string ( + "account-name", + "Account Name", + "Display name for the mail account", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT_BACKEND, + g_param_spec_object ( + "account-backend", + "Account Backend", + "Active mail account service backend", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT_SOURCE, + g_param_spec_object ( + "account-source", + "Account Source", + "Mail account source being edited", + E_TYPE_SOURCE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_IDENTITY_SOURCE, + g_param_spec_object ( + "identity-source", + "Identity Source", + "Mail identity source being edited", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_TRANSPORT_BACKEND, + g_param_spec_object ( + "transport-backend", + "Transport Backend", + "Active mail transport service backend", + E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_TRANSPORT_SOURCE, + g_param_spec_object ( + "transport-source", + "Transport Source", + "Mail transport source being edited", + E_TYPE_SOURCE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + signals[REFRESH] = g_signal_new ( + "refresh", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailConfigSummaryPageClass, refresh), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +e_mail_config_summary_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Account Summary"); + interface->sort_order = E_MAIL_CONFIG_SUMMARY_PAGE_SORT_ORDER; + interface->check_complete = mail_config_summary_page_check_complete; + interface->commit_changes = mail_config_summary_page_commit_changes; +} + +static void +e_mail_config_summary_page_init (EMailConfigSummaryPage *page) +{ + page->priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page); +} + +EMailConfigPage * +e_mail_config_summary_page_new (void) +{ + return g_object_new (E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, NULL); +} + +void +e_mail_config_summary_page_refresh (EMailConfigSummaryPage *page) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page)); + + g_signal_emit (page, signals[REFRESH], 0); +} + +const gchar * +e_mail_config_summary_page_get_account_name (EMailConfigSummaryPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL); + + return page->priv->account_name; +} + +void +e_mail_config_summary_page_set_account_name (EMailConfigSummaryPage *page, + const gchar *account_name) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page)); + + if (account_name == NULL) + account_name = ""; + + g_free (page->priv->account_name); + page->priv->account_name = g_strdup (account_name); + + g_object_notify (G_OBJECT (page), "account-name"); +} + +EMailConfigServiceBackend * +e_mail_config_summary_page_get_account_backend (EMailConfigSummaryPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL); + + return page->priv->account_backend; +} + +void +e_mail_config_summary_page_set_account_backend (EMailConfigSummaryPage *page, + EMailConfigServiceBackend *backend) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page)); + + if (backend != NULL) { + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + g_object_ref (backend); + } + + if (page->priv->account_backend != NULL) + g_object_unref (page->priv->account_backend); + + page->priv->account_backend = backend; + + if (page->priv->account_source != NULL) { + g_signal_handler_disconnect ( + page->priv->account_source, + page->priv->account_source_changed_id); + g_object_unref (page->priv->account_source); + page->priv->account_source = NULL; + page->priv->account_source_changed_id = 0; + } + + if (backend != NULL) { + ESource *source; + gulong handler_id; + + source = e_mail_config_service_backend_get_source (backend); + + handler_id = g_signal_connect ( + source, "changed", + G_CALLBACK (mail_config_summary_page_source_changed), + page); + + page->priv->account_source = g_object_ref (source); + page->priv->account_source_changed_id = handler_id; + } + + g_object_freeze_notify (G_OBJECT (page)); + g_object_notify (G_OBJECT (page), "account-backend"); + g_object_notify (G_OBJECT (page), "account-source"); + g_object_thaw_notify (G_OBJECT (page)); + + e_mail_config_summary_page_refresh (page); +} + +ESource * +e_mail_config_summary_page_get_account_source (EMailConfigSummaryPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL); + + return page->priv->account_source; +} + +ESource * +e_mail_config_summary_page_get_identity_source (EMailConfigSummaryPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL); + + return page->priv->identity_source; +} + +void +e_mail_config_summary_page_set_identity_source (EMailConfigSummaryPage *page, + ESource *identity_source) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page)); + + if (identity_source != NULL) { + g_return_if_fail (E_IS_SOURCE (identity_source)); + g_object_ref (identity_source); + } + + if (page->priv->identity_source != NULL) { + g_signal_handler_disconnect ( + page->priv->identity_source, + page->priv->identity_source_changed_id); + g_object_unref (page->priv->identity_source); + } + + page->priv->identity_source = identity_source; + page->priv->identity_source_changed_id = 0; + + if (identity_source != NULL) { + gulong handler_id; + + handler_id = g_signal_connect ( + identity_source, "changed", + G_CALLBACK (mail_config_summary_page_source_changed), + page); + + page->priv->identity_source_changed_id = handler_id; + } + + g_object_notify (G_OBJECT (page), "identity-source"); + + e_mail_config_summary_page_refresh (page); +} + +EMailConfigServiceBackend * +e_mail_config_summary_page_get_transport_backend (EMailConfigSummaryPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL); + + return page->priv->transport_backend; +} + +void +e_mail_config_summary_page_set_transport_backend (EMailConfigSummaryPage *page, + EMailConfigServiceBackend *backend) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page)); + + if (backend != NULL) { + g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend)); + g_object_ref (backend); + } + + if (page->priv->transport_backend != NULL) + g_object_unref (page->priv->transport_backend); + + page->priv->transport_backend = backend; + + if (page->priv->transport_source != NULL) { + g_signal_handler_disconnect ( + page->priv->transport_source, + page->priv->transport_source_changed_id); + g_object_unref (page->priv->transport_source); + page->priv->transport_source = NULL; + page->priv->transport_source_changed_id = 0; + } + + if (backend != NULL) { + ESource *source; + gulong handler_id; + + source = e_mail_config_service_backend_get_source (backend); + + handler_id = g_signal_connect ( + source, "changed", + G_CALLBACK (mail_config_summary_page_source_changed), + page); + + page->priv->transport_source = g_object_ref (source); + page->priv->transport_source_changed_id = handler_id; + } + + g_object_freeze_notify (G_OBJECT (page)); + g_object_notify (G_OBJECT (page), "transport-backend"); + g_object_notify (G_OBJECT (page), "transport-source"); + g_object_thaw_notify (G_OBJECT (page)); + + e_mail_config_summary_page_refresh (page); +} + +ESource * +e_mail_config_summary_page_get_transport_source (EMailConfigSummaryPage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL); + + return page->priv->transport_source; +} + diff --git a/mail/e-mail-config-summary-page.h b/mail/e-mail-config-summary-page.h new file mode 100644 index 0000000000..564207c9e1 --- /dev/null +++ b/mail/e-mail-config-summary-page.h @@ -0,0 +1,101 @@ +/* + * e-mail-config-summary-page.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_CONFIG_SUMMARY_PAGE_H +#define E_MAIL_CONFIG_SUMMARY_PAGE_H + +#include <gtk/gtk.h> +#include <libedataserver/e-source.h> + +#include <mail/e-mail-config-page.h> +#include <mail/e-mail-config-service-backend.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_SUMMARY_PAGE \ + (e_mail_config_summary_page_get_type ()) +#define E_MAIL_CONFIG_SUMMARY_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPage)) +#define E_MAIL_CONFIG_SUMMARY_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPageClass)) +#define E_IS_MAIL_CONFIG_SUMMARY_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE)) +#define E_IS_MAIL_CONFIG_SUMMARY_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE)) +#define E_MAIL_CONFIG_SUMMARY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPageClass)) + +#define E_MAIL_CONFIG_SUMMARY_PAGE_SORT_ORDER (500) + +G_BEGIN_DECLS + +typedef struct _EMailConfigSummaryPage EMailConfigSummaryPage; +typedef struct _EMailConfigSummaryPageClass EMailConfigSummaryPageClass; +typedef struct _EMailConfigSummaryPagePrivate EMailConfigSummaryPagePrivate; + +struct _EMailConfigSummaryPage { + GtkBox parent; + EMailConfigSummaryPagePrivate *priv; +}; + +struct _EMailConfigSummaryPageClass { + GtkBoxClass parent_class; + + /* Signals */ + void (*refresh) (EMailConfigSummaryPage *page); +}; + +GType e_mail_config_summary_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_summary_page_new (void); +void e_mail_config_summary_page_refresh + (EMailConfigSummaryPage *page); +const gchar * e_mail_config_summary_page_get_account_name + (EMailConfigSummaryPage *page); +void e_mail_config_summary_page_set_account_name + (EMailConfigSummaryPage *page, + const gchar *account_name); +EMailConfigServiceBackend * + e_mail_config_summary_page_get_account_backend + (EMailConfigSummaryPage *page); +void e_mail_config_summary_page_set_account_backend + (EMailConfigSummaryPage *page, + EMailConfigServiceBackend *backend); +ESource * e_mail_config_summary_page_get_account_source + (EMailConfigSummaryPage *page); +ESource * e_mail_config_summary_page_get_identity_source + (EMailConfigSummaryPage *page); +void e_mail_config_summary_page_set_identity_source + (EMailConfigSummaryPage *page, + ESource *identity_source); +EMailConfigServiceBackend * + e_mail_config_summary_page_get_transport_backend + (EMailConfigSummaryPage *page); +void e_mail_config_summary_page_set_transport_backend + (EMailConfigSummaryPage *page, + EMailConfigServiceBackend *backend); +ESource * e_mail_config_summary_page_get_transport_source + (EMailConfigSummaryPage *page); + +#endif /* E_MAIL_CONFIG_SUMMARY_PAGE_H */ + diff --git a/mail/e-mail-config-welcome-page.c b/mail/e-mail-config-welcome-page.c new file mode 100644 index 0000000000..6cb9fd19a6 --- /dev/null +++ b/mail/e-mail-config-welcome-page.c @@ -0,0 +1,203 @@ +/* + * e-mail-config-welcome-page.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-config-welcome-page.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> + +#define E_MAIL_CONFIG_WELCOME_PAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePagePrivate)) + +struct _EMailConfigWelcomePagePrivate { + gchar *text; +}; + +enum { + PROP_0, + PROP_TEXT +}; + +/* Forward Declarations */ +static void e_mail_config_welcome_page_interface_init + (EMailConfigPageInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigWelcomePage, + e_mail_config_welcome_page, + GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_CONFIG_PAGE, + e_mail_config_welcome_page_interface_init)) + +static void +mail_config_welcome_page_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT: + e_mail_config_welcome_page_set_text ( + E_MAIL_CONFIG_WELCOME_PAGE (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_welcome_page_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT: + g_value_set_string ( + value, + e_mail_config_welcome_page_get_text ( + E_MAIL_CONFIG_WELCOME_PAGE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_welcome_page_finalize (GObject *object) +{ + EMailConfigWelcomePagePrivate *priv; + + priv = E_MAIL_CONFIG_WELCOME_PAGE_GET_PRIVATE (object); + + g_free (priv->text); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_config_welcome_page_parent_class)-> + finalize (object); +} + +static void +mail_config_welcome_page_constructed (GObject *object) +{ + EMailConfigWelcomePage *page; + GtkWidget *widget; + + page = E_MAIL_CONFIG_WELCOME_PAGE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_welcome_page_parent_class)-> + constructed (object); + + gtk_orientable_set_orientation ( + GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL); + + gtk_box_set_spacing (GTK_BOX (page), 12); + + gtk_widget_set_valign (GTK_WIDGET (page), GTK_ALIGN_CENTER); + + widget = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_object_bind_property ( + page, "text", + widget, "label", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_extensible_load_extensions (E_EXTENSIBLE (page)); +} + +static void +e_mail_config_welcome_page_class_init (EMailConfigWelcomePageClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private ( + class, sizeof (EMailConfigWelcomePagePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_welcome_page_set_property; + object_class->get_property = mail_config_welcome_page_get_property; + object_class->finalize = mail_config_welcome_page_finalize; + object_class->constructed = mail_config_welcome_page_constructed; + + g_object_class_install_property ( + object_class, + PROP_TEXT, + g_param_spec_string ( + "text", + "Text", + "Welcome message", + _("Welcome to the Evolution Mail Configuration " + "Assistant.\n\nClick \"Continue\" to begin."), + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_welcome_page_interface_init (EMailConfigPageInterface *interface) +{ + interface->title = _("Welcome"); + interface->page_type = GTK_ASSISTANT_PAGE_INTRO; + interface->sort_order = E_MAIL_CONFIG_WELCOME_PAGE_SORT_ORDER; +} + +static void +e_mail_config_welcome_page_init (EMailConfigWelcomePage *page) +{ + page->priv = E_MAIL_CONFIG_WELCOME_PAGE_GET_PRIVATE (page); +} + +EMailConfigPage * +e_mail_config_welcome_page_new (void) +{ + return g_object_new (E_TYPE_MAIL_CONFIG_WELCOME_PAGE, NULL); +} + +const gchar * +e_mail_config_welcome_page_get_text (EMailConfigWelcomePage *page) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_WELCOME_PAGE (page), NULL); + + return page->priv->text; +} + +void +e_mail_config_welcome_page_set_text (EMailConfigWelcomePage *page, + const gchar *text) +{ + g_return_if_fail (E_IS_MAIL_CONFIG_WELCOME_PAGE (page)); + + g_free (page->priv->text); + page->priv->text = g_strdup ((text != NULL) ? text : ""); + + g_object_notify (G_OBJECT (page), "text"); +} + diff --git a/mail/e-mail-config-welcome-page.h b/mail/e-mail-config-welcome-page.h new file mode 100644 index 0000000000..a7665ecc56 --- /dev/null +++ b/mail/e-mail-config-welcome-page.h @@ -0,0 +1,75 @@ +/* + * e-mail-config-welcome-page.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_CONFIG_WELCOME_PAGE_H +#define E_MAIL_CONFIG_WELCOME_PAGE_H + +#include <gtk/gtk.h> + +#include <mail/e-mail-config-page.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_WELCOME_PAGE \ + (e_mail_config_welcome_page_get_type ()) +#define E_MAIL_CONFIG_WELCOME_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePage)) +#define E_MAIL_CONFIG_WELCOME_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePageClass)) +#define E_IS_MAIL_CONFIG_WELCOME_PAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE)) +#define E_IS_MAIL_CONFIG_WELCOME_PAGE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_WELCOME_PAGE)) +#define E_MAIL_CONFIG_WELCOME_PAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePageClass)) + +#define E_MAIL_CONFIG_WELCOME_PAGE_SORT_ORDER (0) + +G_BEGIN_DECLS + +typedef struct _EMailConfigWelcomePage EMailConfigWelcomePage; +typedef struct _EMailConfigWelcomePageClass EMailConfigWelcomePageClass; +typedef struct _EMailConfigWelcomePagePrivate EMailConfigWelcomePagePrivate; + +struct _EMailConfigWelcomePage { + GtkBox parent; + EMailConfigWelcomePagePrivate *priv; +}; + +struct _EMailConfigWelcomePageClass { + GtkBoxClass parent_class; +}; + +GType e_mail_config_welcome_page_get_type + (void) G_GNUC_CONST; +EMailConfigPage * + e_mail_config_welcome_page_new (void); +const gchar * e_mail_config_welcome_page_get_text + (EMailConfigWelcomePage *page); +void e_mail_config_welcome_page_set_text + (EMailConfigWelcomePage *page, + const gchar *text); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_WELCOME_PAGE_H */ + diff --git a/mail/e-mail-config-window.c b/mail/e-mail-config-window.c new file mode 100644 index 0000000000..746e1c3e80 --- /dev/null +++ b/mail/e-mail-config-window.c @@ -0,0 +1,524 @@ +/* + * e-mail-config-window.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-config-window.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <libedataserver/e-source-collection.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-submission.h> + +#include <libevolution-utils/e-alert-dialog.h> +#include <libevolution-utils/e-alert-sink.h> +#include <misc/e-alert-bar.h> + +#include <mail/e-mail-config-notebook.h> +#include <mail/e-mail-config-sidebar.h> + +#define E_MAIL_CONFIG_WINDOW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindowPrivate)) + +struct _EMailConfigWindowPrivate { + EMailSession *session; + ESource *original_source; + + /* Scratch Sources */ + ESource *account_source; + ESource *identity_source; + ESource *transport_source; + ESource *collection_source; /* optional */ + + GtkWidget *notebook; /* not referenced */ + GtkWidget *alert_bar; /* not referenced */ +}; + +enum { + PROP_0, + PROP_ORIGINAL_SOURCE, + PROP_SESSION +}; + +/* Forward Declarations */ +static void e_mail_config_window_alert_sink_init + (EAlertSinkInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailConfigWindow, + e_mail_config_window, + GTK_TYPE_DIALOG, + G_IMPLEMENT_INTERFACE ( + E_TYPE_ALERT_SINK, + e_mail_config_window_alert_sink_init)) + +static ESource * +mail_config_window_clone_source (ESource *source) +{ + ESource *clone; + GDBusObject *dbus_object; + + dbus_object = e_source_ref_dbus_object (source); + + clone = e_source_new (dbus_object, NULL, NULL); + + if (dbus_object != NULL) + g_object_unref (dbus_object); + + return clone; +} + +static void +mail_config_window_setup_scratch_sources (EMailConfigWindow *window) +{ + ESource *source; + ESource *scratch_source; + ESourceRegistry *registry; + ESourceMailAccount *account_ext; + ESourceMailSubmission *submission_ext; + EMailSession *session; + const gchar *extension_name; + const gchar *uid; + + session = e_mail_config_window_get_session (window); + registry = e_mail_session_get_registry (session); + + source = window->priv->original_source; + scratch_source = mail_config_window_clone_source (source); + window->priv->account_source = scratch_source; + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + account_ext = e_source_get_extension (source, extension_name); + uid = e_source_mail_account_get_identity_uid (account_ext); + source = e_source_registry_ref_source (registry, uid); + scratch_source = mail_config_window_clone_source (source); + window->priv->identity_source = scratch_source; + g_object_unref (source); + + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + submission_ext = e_source_get_extension (source, extension_name); + uid = e_source_mail_submission_get_transport_uid (submission_ext); + source = e_source_registry_ref_source (registry, uid); + scratch_source = mail_config_window_clone_source (source); + window->priv->transport_source = scratch_source; + g_object_unref (source); + + extension_name = E_SOURCE_EXTENSION_COLLECTION; + source = e_source_registry_find_extension ( + registry, window->priv->original_source, extension_name); + if (source != NULL) { + scratch_source = mail_config_window_clone_source (source); + window->priv->collection_source = scratch_source; + g_object_unref (source); + } +} + +static void +mail_config_window_commit_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + EMailConfigWindow *window; + EMailConfigNotebook *notebook; + GdkWindow *gdk_window; + GError *error = NULL; + + window = E_MAIL_CONFIG_WINDOW (user_data); + notebook = E_MAIL_CONFIG_NOTEBOOK (object); + + /* Set the cursor back to normal. */ + gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); + gdk_window_set_cursor (gdk_window, NULL); + + /* Allow user interaction with window content. */ + gtk_widget_set_sensitive (GTK_WIDGET (window), TRUE); + + e_mail_config_notebook_commit_finish (notebook, result, &error); + + /* Ignore cancellations. */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_object_unref (window); + g_error_free (error); + + } else if (error != NULL) { + e_alert_submit ( + E_ALERT_SINK (window), + "mail:session-message-error", + error->message, NULL); + g_object_unref (window); + g_error_free (error); + + } else { + gtk_widget_destroy (GTK_WIDGET (window)); + } +} + +static void +mail_config_window_commit (EMailConfigWindow *window) +{ + GdkCursor *gdk_cursor; + GdkWindow *gdk_window; + EMailConfigNotebook *notebook; + + notebook = E_MAIL_CONFIG_NOTEBOOK (window->priv->notebook); + + /* Clear any previous alerts. */ + e_alert_bar_clear (E_ALERT_BAR (window->priv->alert_bar)); + + /* Make the cursor appear busy. */ + gdk_cursor = gdk_cursor_new (GDK_WATCH); + gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); + gdk_window_set_cursor (gdk_window, gdk_cursor); + g_object_unref (gdk_cursor); + + /* Prevent user interaction with window content. */ + gtk_widget_set_sensitive (GTK_WIDGET (window), FALSE); + + /* XXX This operation is not cancellable. */ + e_mail_config_notebook_commit ( + notebook, NULL, + mail_config_window_commit_cb, + g_object_ref (window)); +} + +static void +mail_config_window_set_original_source (EMailConfigWindow *window, + ESource *original_source) +{ + g_return_if_fail (E_IS_SOURCE (original_source)); + g_return_if_fail (window->priv->original_source == NULL); + + window->priv->original_source = g_object_ref (original_source); +} + +static void +mail_config_window_set_session (EMailConfigWindow *window, + EMailSession *session) +{ + g_return_if_fail (E_IS_MAIL_SESSION (session)); + g_return_if_fail (window->priv->session == NULL); + + window->priv->session = g_object_ref (session); +} + +static void +mail_config_window_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ORIGINAL_SOURCE: + mail_config_window_set_original_source ( + E_MAIL_CONFIG_WINDOW (object), + g_value_get_object (value)); + return; + + case PROP_SESSION: + mail_config_window_set_session ( + E_MAIL_CONFIG_WINDOW (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_window_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ORIGINAL_SOURCE: + g_value_set_object ( + value, + e_mail_config_window_get_original_source ( + E_MAIL_CONFIG_WINDOW (object))); + return; + + case PROP_SESSION: + g_value_set_object ( + value, + e_mail_config_window_get_session ( + E_MAIL_CONFIG_WINDOW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_config_window_dispose (GObject *object) +{ + EMailConfigWindowPrivate *priv; + + priv = E_MAIL_CONFIG_WINDOW_GET_PRIVATE (object); + + if (priv->session != NULL) { + g_object_unref (priv->session); + priv->session = NULL; + } + + if (priv->original_source != NULL) { + g_object_unref (priv->original_source); + priv->original_source = NULL; + } + + if (priv->account_source != NULL) { + g_object_unref (priv->account_source); + priv->account_source = NULL; + } + + if (priv->identity_source != NULL) { + g_object_unref (priv->identity_source); + priv->identity_source = NULL; + } + + if (priv->transport_source != NULL) { + g_object_unref (priv->transport_source); + priv->transport_source = NULL; + } + + if (priv->collection_source != NULL) { + g_object_unref (priv->collection_source); + priv->collection_source = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_config_window_parent_class)->dispose (object); +} + +static void +mail_config_window_constructed (GObject *object) +{ + EMailConfigWindow *window; + GtkWidget *container; + GtkWidget *widget; + + window = E_MAIL_CONFIG_WINDOW (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_config_window_parent_class)-> + constructed (object); + + mail_config_window_setup_scratch_sources (window); + + gtk_container_set_border_width (GTK_CONTAINER (window), 5); + gtk_window_set_title (GTK_WINDOW (window), _("Account Editor")); + gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER); + + gtk_dialog_add_buttons ( + GTK_DIALOG (window), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); + + container = gtk_dialog_get_content_area (GTK_DIALOG (window)); + + widget = gtk_grid_new (); + gtk_grid_set_column_spacing (GTK_GRID (widget), 12); + gtk_container_set_border_width (GTK_CONTAINER (widget), 5); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = e_alert_bar_new (); + gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 3, 1); + window->priv->alert_bar = widget; /* not referenced */ + /* EAlertBar controls its own visibility. */ + + /* Add an extra-wide margin to the left and bottom. + * + * XXX The bottom margin is tricky. We want a 24px margin between + * the notebook and the dialog action buttons, but we have to + * take style property defaults into consideration: + * + * 24 - action-area-border (5) - content-area-border (2) = 17 + */ + widget = e_mail_config_notebook_new ( + window->priv->session, + window->priv->account_source, + window->priv->identity_source, + window->priv->transport_source, + window->priv->collection_source); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_vexpand (widget, TRUE); + gtk_widget_set_margin_bottom (widget, 17); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); + gtk_grid_attach (GTK_GRID (container), widget, 2, 1, 1, 1); + window->priv->notebook = widget; /* not referenced */ + gtk_widget_show (widget); + + widget = gtk_separator_new (GTK_ORIENTATION_VERTICAL); + gtk_widget_set_vexpand (widget, TRUE); + gtk_widget_set_valign (widget, GTK_ALIGN_FILL); + gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1); + gtk_widget_show (widget); + + widget = e_mail_config_sidebar_new ( + E_MAIL_CONFIG_NOTEBOOK (window->priv->notebook)); + gtk_widget_set_vexpand (widget, TRUE); + gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1); + gtk_widget_show (widget); + + /* Make the Apply button insensitive when required + * fields in the notebook pages are incomplete. */ + + widget = gtk_dialog_get_widget_for_response ( + GTK_DIALOG (window), GTK_RESPONSE_OK); + + g_object_bind_property ( + window->priv->notebook, "complete", + widget, "sensitive", + G_BINDING_SYNC_CREATE); +} + +static void +mail_config_window_response (GtkDialog *dialog, + gint response_id) +{ + /* Do not chain up. GtkDialog does not implement this method. */ + + switch (response_id) { + case GTK_RESPONSE_OK: + mail_config_window_commit ( + E_MAIL_CONFIG_WINDOW (dialog)); + break; + case GTK_RESPONSE_CANCEL: + gtk_widget_destroy (GTK_WIDGET (dialog)); + break; + default: + break; + } +} + +static void +mail_config_window_submit_alert (EAlertSink *alert_sink, + EAlert *alert) +{ + EMailConfigWindowPrivate *priv; + EAlertBar *alert_bar; + GtkWidget *dialog; + GtkWindow *parent; + + priv = E_MAIL_CONFIG_WINDOW_GET_PRIVATE (alert_sink); + + switch (e_alert_get_message_type (alert)) { + case GTK_MESSAGE_INFO: + case GTK_MESSAGE_WARNING: + case GTK_MESSAGE_ERROR: + alert_bar = E_ALERT_BAR (priv->alert_bar); + e_alert_bar_add_alert (alert_bar, alert); + break; + + default: + parent = GTK_WINDOW (alert_sink); + dialog = e_alert_dialog_new (parent, alert); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + break; + } +} + +static void +e_mail_config_window_class_init (EMailConfigWindowClass *class) +{ + GObjectClass *object_class; + GtkDialogClass *dialog_class; + + g_type_class_add_private (class, sizeof (EMailConfigWindowPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_config_window_set_property; + object_class->get_property = mail_config_window_get_property; + object_class->dispose = mail_config_window_dispose; + object_class->constructed = mail_config_window_constructed; + + dialog_class = GTK_DIALOG_CLASS (class); + dialog_class->response = mail_config_window_response; + + g_object_class_install_property ( + object_class, + PROP_ORIGINAL_SOURCE, + g_param_spec_object ( + "original-source", + "Original Source", + "Original mail account source", + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SESSION, + g_param_spec_object ( + "session", + "Session", + "Mail session", + E_TYPE_MAIL_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_mail_config_window_alert_sink_init (EAlertSinkInterface *interface) +{ + interface->submit_alert = mail_config_window_submit_alert; +} + +static void +e_mail_config_window_init (EMailConfigWindow *window) +{ + window->priv = E_MAIL_CONFIG_WINDOW_GET_PRIVATE (window); +} + +GtkWidget * +e_mail_config_window_new (EMailSession *session, + ESource *original_source) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + g_return_val_if_fail (E_IS_SOURCE (original_source), NULL); + + return g_object_new ( + E_TYPE_MAIL_CONFIG_WINDOW, + "original-source", original_source, + "session", session, NULL); +} + +EMailSession * +e_mail_config_window_get_session (EMailConfigWindow *window) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_WINDOW (window), NULL); + + return window->priv->session; +} + +ESource * +e_mail_config_window_get_original_source (EMailConfigWindow *window) +{ + g_return_val_if_fail (E_IS_MAIL_CONFIG_WINDOW (window), NULL); + + return window->priv->original_source; +} + diff --git a/mail/e-mail-config-window.h b/mail/e-mail-config-window.h new file mode 100644 index 0000000000..78a7c073b8 --- /dev/null +++ b/mail/e-mail-config-window.h @@ -0,0 +1,71 @@ +/* + * e-mail-config-window.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_CONFIG_WINDOW_H +#define E_MAIL_CONFIG_WINDOW_H + +#include <gtk/gtk.h> + +#include <libemail-engine/e-mail-session.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_CONFIG_WINDOW \ + (e_mail_config_window_get_type ()) +#define E_MAIL_CONFIG_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindow)) +#define E_MAIL_CONFIG_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindowClass)) +#define E_IS_MAIL_CONFIG_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_CONFIG_WINDOW)) +#define E_IS_MAIL_CONFIG_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_CONFIG_WINDOW)) +#define E_MAIL_CONFIG_WINDOW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindowClass)) + +G_BEGIN_DECLS + +typedef struct _EMailConfigWindow EMailConfigWindow; +typedef struct _EMailConfigWindowClass EMailConfigWindowClass; +typedef struct _EMailConfigWindowPrivate EMailConfigWindowPrivate; + +struct _EMailConfigWindow { + GtkDialog parent; + EMailConfigWindowPrivate *priv; +}; + +struct _EMailConfigWindowClass { + GtkDialogClass parent_class; +}; + +GType e_mail_config_window_get_type (void) G_GNUC_CONST; +GtkWidget * e_mail_config_window_new (EMailSession *session, + ESource *original_source); +EMailSession * e_mail_config_window_get_session + (EMailConfigWindow *window); +ESource * e_mail_config_window_get_original_source + (EMailConfigWindow *window); + +G_END_DECLS + +#endif /* E_MAIL_CONFIG_WINDOW_H */ + diff --git a/mail/e-mail-folder-pane.c b/mail/e-mail-folder-pane.c index 7e0457e3bd..03168cec18 100644 --- a/mail/e-mail-folder-pane.c +++ b/mail/e-mail-folder-pane.c @@ -74,7 +74,10 @@ folder_pane_set_preview_visible (EMailView *view, static guint mail_paned_view_open_selected_mail (EMailPanedView *view) { + EShell *shell; EMailReader *reader; + EMailBackend *backend; + ESourceRegistry *registry; GPtrArray *uids; gint i; GtkWindow *window; @@ -88,6 +91,10 @@ mail_paned_view_open_selected_mail (EMailPanedView *view) uids = e_mail_reader_get_selected_uids (reader); g_return_val_if_fail (uids != NULL, 0); + backend = e_mail_reader_get_backend (reader); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + registry = e_shell_get_registry (shell); + /* XXX Either e_mail_reader_get_selected_uids() * or MessageList should do this itself. */ g_ptr_array_set_free_func (uids, (GDestroyNotify) g_free); @@ -97,9 +104,9 @@ mail_paned_view_open_selected_mail (EMailPanedView *view) return 0; } - if (em_utils_folder_is_drafts (folder) || - em_utils_folder_is_outbox (folder) || - em_utils_folder_is_templates (folder)) { + if (em_utils_folder_is_drafts (registry, folder) || + em_utils_folder_is_outbox (registry, folder) || + em_utils_folder_is_templates (registry, folder)) { em_utils_edit_messages (reader, folder, uids, TRUE); g_ptr_array_unref (uids); return 0; @@ -127,8 +134,8 @@ mail_paned_view_open_selected_mail (EMailPanedView *view) CAMEL_VEE_FOLDER (folder), (CamelVeeMessageInfo *) info, &real_uid); - if (em_utils_folder_is_drafts (real_folder) || - em_utils_folder_is_outbox (real_folder)) { + if (em_utils_folder_is_drafts (registry, real_folder) || + em_utils_folder_is_outbox (registry, real_folder)) { GPtrArray *edits; edits = g_ptr_array_new_with_free_func ( diff --git a/mail/e-mail-migrate.c b/mail/e-mail-migrate.c index ffc5f1a264..a485a1e0d2 100644 --- a/mail/e-mail-migrate.c +++ b/mail/e-mail-migrate.c @@ -50,6 +50,9 @@ #include <libedataserver/e-xml-utils.h> #include <libedataserver/e-data-server-util.h> +#include <libedataserver/e-source-camel.h> +#include <libedataserver/e-source-registry.h> +#include <libedataserver/e-source-mail-account.h> #include <shell/e-shell.h> #include <shell/e-shell-migrate.h> @@ -61,9 +64,6 @@ #include <e-util/e-util-private.h> #include <e-util/e-plugin.h> -#include <libemail-utils/e-account-utils.h> -#include <libemail-utils/e-signature-utils.h> - #include <libemail-engine/e-mail-folder-utils.h> #include "e-mail-backend.h" @@ -221,50 +221,6 @@ cp (const gchar *src, return FALSE; } -#ifndef G_OS_WIN32 - -#define SUBFOLDER_DIR_NAME "subfolders" -#define SUBFOLDER_DIR_NAME_LEN 10 - -static void -em_update_accounts_2_11 (void) -{ - EAccountList *accounts; - EIterator *iter; - gboolean changed = FALSE; - - if (!(accounts = e_get_account_list ())) - return; - - iter = e_list_get_iterator ((EList *) accounts); - while (e_iterator_is_valid (iter)) { - EAccount *account = (EAccount *) e_iterator_get (iter); - - if (g_str_has_prefix (account->source->url, "spool://")) { - if (g_file_test (account->source->url + 8, G_FILE_TEST_IS_DIR)) { - gchar *str; - - str = g_strdup_printf ( - "spooldir://%s", - account->source->url + 8); - - g_free (account->source->url); - account->source->url = str; - changed = TRUE; - } - } - - e_iterator_next (iter); - } - - g_object_unref (iter); - - if (changed) - e_account_list_save (accounts); -} - -#endif /* !G_OS_WIN32 */ - static gboolean emm_setup_initial (const gchar *data_dir) { @@ -600,27 +556,67 @@ static gboolean migrate_mbox_to_maildir (EShellBackend *shell_backend, EMMigrateSession *session) { - CamelService *mbox_service, *maildir_service; - CamelStore *mbox_store, *maildir_store; + EShell *shell; + ESource *source; + ESourceRegistry *registry; + ESourceExtension *extension; + const gchar *extension_name; + CamelService *mbox_service; + CamelService *maildir_service; + CamelStore *mbox_store; + CamelStore *maildir_store; CamelSettings *settings; const gchar *data_dir; + const gchar *uid; gchar *path; struct MigrateStore ms; + GError *error = NULL; data_dir = e_shell_backend_get_data_dir (shell_backend); + shell = e_shell_backend_get_shell (shell_backend); + registry = e_shell_get_registry (shell); + + source = e_source_new (NULL, NULL, NULL); + e_source_set_display_name (source, "local_mbox"); - mbox_service = camel_session_add_service ( - CAMEL_SESSION (session), "local_mbox", "mbox", - CAMEL_PROVIDER_STORE, NULL); + uid = e_source_get_uid (source); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + extension = e_source_get_extension (source, extension_name); + + e_source_backend_set_backend_name ( + E_SOURCE_BACKEND (extension), "mbox"); + + extension_name = e_source_camel_get_extension_name ("mbox"); + extension = e_source_get_extension (source, extension_name); + settings = e_source_camel_get_settings (E_SOURCE_CAMEL (extension)); - settings = camel_service_get_settings (mbox_service); path = g_build_filename (data_dir, "local_mbox", NULL); g_object_set (settings, "path", path, NULL); g_free (path); - maildir_service = camel_session_add_service ( - CAMEL_SESSION (session), "local", "maildir", - CAMEL_PROVIDER_STORE, NULL); + e_source_registry_commit_source_sync ( + registry, source, NULL, &error); + + if (error == NULL) + mbox_service = camel_session_add_service ( + CAMEL_SESSION (session), uid, "mbox", + CAMEL_PROVIDER_STORE, &error); + + if (error == NULL) + maildir_service = camel_session_add_service ( + CAMEL_SESSION (session), "local", "maildir", + CAMEL_PROVIDER_STORE, &error); + + g_object_unref (source); + + if (error != NULL) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + return FALSE; + } + + camel_service_set_settings (mbox_service, settings); settings = camel_service_get_settings (maildir_service); path = g_build_filename (data_dir, "local", NULL); @@ -667,412 +663,6 @@ exit: } static gboolean -create_mbox_account (EShellBackend *shell_backend, - EMMigrateSession *session) -{ - EMailBackend *mail_backend; - EMailSession *mail_session; - CamelService *service; - CamelURL *url; - EAccountList *accounts; - EAccount *account; - const gchar *data_dir; - gchar *name, *id, *temp, *uri, *folder_uri; - - mail_backend = E_MAIL_BACKEND (shell_backend); - mail_session = e_mail_backend_get_session (mail_backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); - - account = e_account_new (); - account->enabled = TRUE; - - g_free (account->uid); - account->uid = g_strdup ("local_mbox"); - - url = camel_url_new ("mbox:", NULL); - temp = g_build_filename (data_dir, "local_mbox", NULL); - camel_url_set_path (url, temp); - g_free (temp); - - uri = camel_url_to_string (url, 0); - e_account_set_string (account, E_ACCOUNT_SOURCE_URL, uri); - -#ifndef G_OS_WIN32 - name = g_locale_to_utf8 (g_get_user_name (), -1, NULL, NULL, NULL); -#else - name = g_strdup (g_get_user_name ()); -#endif - - id = g_strconcat (name, "@", "localhost", NULL); - e_account_set_string (account, E_ACCOUNT_ID_NAME, name); - e_account_set_string (account, E_ACCOUNT_ID_ADDRESS, id); - e_account_set_string (account, E_ACCOUNT_NAME, id); - - accounts = e_get_account_list (); - if (e_account_list_find (accounts, E_ACCOUNT_ID_ADDRESS, id)) { - g_object_unref (account); - goto exit; - } - - /* This will also add it to the EMailSession. */ - e_account_list_add (accounts, account); - - service = camel_session_get_service ( - CAMEL_SESSION (mail_session), account->uid); - - folder_uri = e_mail_folder_uri_build ( - CAMEL_STORE (service), "Sent"); - e_account_set_string ( - account, E_ACCOUNT_SENT_FOLDER_URI, folder_uri); - g_free (folder_uri); - - folder_uri = e_mail_folder_uri_build ( - CAMEL_STORE (service), "Drafts"); - e_account_set_string ( - account, E_ACCOUNT_DRAFTS_FOLDER_URI, folder_uri); - g_free (folder_uri); - - e_account_list_save (accounts); - -exit: - camel_url_free (url); - g_free (uri); - g_free (name); - g_free (id); - - return TRUE; -} - -static void -change_sent_and_drafts_local_folders (EShellBackend *shell_backend) -{ - EMailBackend *backend; - EMailSession *session; - EAccountList *accounts; - EIterator *iter; - const gchar *data_dir; - gboolean changed = FALSE; - CamelURL *url; - gchar *tmp_uri, *drafts_uri, *sent_uri, *old_drafts_uri, *old_sent_uri; - - accounts = e_get_account_list (); - if (!accounts) - return; - - backend = E_MAIL_BACKEND (shell_backend); - session = e_mail_backend_get_session (backend); - - data_dir = e_shell_backend_get_data_dir (shell_backend); - - tmp_uri = g_strconcat ("mbox:", data_dir, "/", "local", NULL); - url = camel_url_new (tmp_uri, NULL); - g_free (tmp_uri); - - g_return_if_fail (url != NULL); - - camel_url_set_fragment (url, "Drafts"); - drafts_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - - camel_url_set_fragment (url, "Sent"); - sent_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - - camel_url_free (url); - - tmp_uri = g_strconcat ( - "mbox:", g_get_home_dir (), - "/.evolution/mail/local", NULL); - url = camel_url_new (tmp_uri, NULL); - g_free (tmp_uri); - - g_return_if_fail (url != NULL); - - camel_url_set_fragment (url, "Drafts"); - old_drafts_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - - camel_url_set_fragment (url, "Sent"); - old_sent_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - - camel_url_free (url); - - for (iter = e_list_get_iterator ((EList *) accounts); - e_iterator_is_valid (iter); e_iterator_next (iter)) { - EAccount *account = (EAccount *) e_iterator_get (iter); - const gchar *uri; - - if (!account) - continue; - - uri = e_account_get_string (account, E_ACCOUNT_DRAFTS_FOLDER_URI); - if (g_strcmp0 (uri, drafts_uri) == 0 || - g_strcmp0 (uri, old_drafts_uri) == 0) { - changed = TRUE; - e_account_set_string ( - account, E_ACCOUNT_DRAFTS_FOLDER_URI, - e_mail_session_get_local_folder_uri ( - session, E_MAIL_LOCAL_FOLDER_DRAFTS)); - } - - uri = e_account_get_string (account, E_ACCOUNT_SENT_FOLDER_URI); - if (g_strcmp0 (uri, sent_uri) == 0 || g_strcmp0 (uri, old_sent_uri) == 0) { - changed = TRUE; - e_account_set_string ( - account, E_ACCOUNT_SENT_FOLDER_URI, - e_mail_session_get_local_folder_uri ( - session, E_MAIL_LOCAL_FOLDER_SENT)); - } - } - - g_object_unref (iter); - g_free (old_drafts_uri); - g_free (drafts_uri); - g_free (old_sent_uri); - g_free (sent_uri); - - if (changed) - e_account_list_save (accounts); -} - -static void -em_rename_camel_url_params (CamelURL *url) -{ - /* This list includes known URL parameters from built-in providers - * in Camel, as well as from evolution-exchange, evolution-groupwise, - * and evolution-mapi. Add more as needed. */ - static struct { - const gchar *url_parameter; - const gchar *property_name; - } camel_url_conversion[] = { - { "account_uid", "account-uid" }, - { "ad_auth", "gc-auth-method" }, - { "ad_browse", "gc-allow-browse" }, - { "ad_expand_groups", "gc-expand-groups" }, - { "ad_limit", "gc-results-limit" }, - { "ad_server", "gc-server-name" }, - { "all_headers", "fetch-headers" }, - { "basic_headers", "fetch-headers" }, - { "cachedconn" "concurrent-connections" }, - { "check_all", "check-all" }, - { "check_lsub", "check-subscribed" }, - { "command", "shell-command" }, - { "delete_after", "delete-after-days" }, - { "delete_expunged", "delete-expunged" }, - { "disable_extensions", "disable-extensions" }, - { "dotfolders", "use-dot-folders" }, - { "filter", "filter-inbox" }, - { "filter_junk", "filter-junk" }, - { "filter_junk_inbox", "filter-junk-inbox" }, - { "folder_hierarchy_relative", "folder-hierarchy-relative" }, - { "imap_custom_headers", "fetch-headers-extra" }, - { "keep_on_server", "keep-on-server" }, - { "oab_offline", "oab-offline" }, - { "oal_selected", "oal-selected" }, - { "offline_sync", "stay-synchronized" }, - { "override_namespace", "use-namespace" }, - { "owa_path", "owa-path" }, - { "owa_url", "owa-url" }, - { "password_exp_warn_period", "password-exp-warn-period" }, - { "real_junk_path", "real-junk-path" }, - { "real_trash_path", "real-trash-path" }, - { "show_short_notation", "short-folder-names" }, - { "soap_port", "soap-port" }, - { "ssl", "security-method" }, - { "sync_offline", "stay-synchronized" }, - { "use_command", "use-shell-command" }, - { "use_idle", "use-idle" }, - { "use_lsub", "use-subscriptions" }, - { "use_qresync", "use-qresync" }, - { "use_ssl", "security-method" }, - { "xstatus", "use-xstatus-headers" } - }; - - const gchar *param; - const gchar *use_param; - gint ii; - - for (ii = 0; ii < G_N_ELEMENTS (camel_url_conversion); ii++) { - const gchar *key; - gpointer value; - - key = camel_url_conversion[ii].url_parameter; - value = g_datalist_get_data (&url->params, key); - - if (value == NULL) - continue; - - g_datalist_remove_no_notify (&url->params, key); - - key = camel_url_conversion[ii].property_name; - - /* Deal with a few special enum cases where - * the parameter value also needs renamed. */ - - if (strcmp (key, "all_headers") == 0) { - GEnumClass *enum_class; - GEnumValue *enum_value; - - enum_class = g_type_class_ref ( - CAMEL_TYPE_FETCH_HEADERS_TYPE); - enum_value = g_enum_get_value ( - enum_class, CAMEL_FETCH_HEADERS_ALL); - if (enum_value != NULL) { - g_free (value); - value = g_strdup (enum_value->value_nick); - } else - g_warn_if_reached (); - g_type_class_unref (enum_class); - } - - if (strcmp (key, "basic_headers") == 0) { - GEnumClass *enum_class; - GEnumValue *enum_value; - - enum_class = g_type_class_ref ( - CAMEL_TYPE_FETCH_HEADERS_TYPE); - enum_value = g_enum_get_value ( - enum_class, CAMEL_FETCH_HEADERS_BASIC); - if (enum_value != NULL) { - g_free (value); - value = g_strdup (enum_value->value_nick); - } else - g_warn_if_reached (); - g_type_class_unref (enum_class); - } - - if (strcmp (key, "imap_custom_headers") == 0) - g_strdelimit (value, " ", ','); - - if (strcmp (key, "security-method") == 0) { - CamelNetworkSecurityMethod method; - GEnumClass *enum_class; - GEnumValue *enum_value; - - if (strcmp (value, "always") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT; - else if (strcmp (value, "1") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT; - else if (strcmp (value, "when-possible") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT; - else - method = CAMEL_NETWORK_SECURITY_METHOD_NONE; - - enum_class = g_type_class_ref ( - CAMEL_TYPE_NETWORK_SECURITY_METHOD); - enum_value = g_enum_get_value (enum_class, method); - if (enum_value != NULL) { - g_free (value); - value = g_strdup (enum_value->value_nick); - } else - g_warn_if_reached (); - g_type_class_unref (enum_class); - } - - g_datalist_set_data_full (&url->params, key, value, g_free); - } - - /* A few more adjustments... - * - * These are all CAMEL_PROVIDER_CONF_CHECKSPIN settings. The spin - * button value is bound to "param" and the checkbox state is bound - * to "use-param". The "use-param" settings are new. If "param" - * exists but no "use-param", then set "use-param" to "true". */ - - param = g_datalist_get_data (&url->params, "gc-results-limit"); - use_param = g_datalist_get_data (&url->params, "use-gc-results-limit"); - if (param != NULL && *param != '\0' && use_param == NULL) { - g_datalist_set_data_full ( - &url->params, "use-gc-results-limit", - g_strdup ("true"), (GDestroyNotify) g_free); - } - - param = g_datalist_get_data (&url->params, "kerberos"); - if (g_strcmp0 (param, "required") == 0) { - g_datalist_set_data_full ( - &url->params, "kerberos", - g_strdup ("true"), (GDestroyNotify) g_free); - } - - param = g_datalist_get_data ( - &url->params, "password-exp-warn-period"); - use_param = g_datalist_get_data ( - &url->params, "use-password-exp-warn-period"); - if (param != NULL && *param != '\0' && use_param == NULL) { - g_datalist_set_data_full ( - &url->params, "use-password-exp-warn-period", - g_strdup ("true"), (GDestroyNotify) g_free); - } - - param = g_datalist_get_data (&url->params, "real-junk-path"); - use_param = g_datalist_get_data (&url->params, "use-real-junk-path"); - if (param != NULL && *param != '\0' && use_param == NULL) { - g_datalist_set_data_full ( - &url->params, "use-real-junk-path", - g_strdup ("true"), (GDestroyNotify) g_free); - } - - param = g_datalist_get_data (&url->params, "real-trash-path"); - use_param = g_datalist_get_data (&url->params, "use-real-trash-path"); - if (param != NULL && *param != '\0' && use_param == NULL) { - g_datalist_set_data_full ( - &url->params, "use-real-trash-path", - g_strdup ("true"), (GDestroyNotify) g_free); - } -} - -static void -em_rename_account_params (void) -{ - EAccountList *account_list; - EIterator *iterator; - - /* XXX As of 3.2, CamelServices store settings in GObject properties, - * not CamelURL parameters. CamelURL parameters are still used - * for storage in GConf until we can move account information to - * key files, but this is only within Evolution. Some of the new - * GObject property names differ from the old CamelURL parameter - * names. This routine renames the CamelURL parameter names to - * the GObject property names for all accounts, both the source - * and tranport URLs. */ - - account_list = e_get_account_list (); - iterator = e_list_get_iterator (E_LIST (account_list)); - - while (e_iterator_is_valid (iterator)) { - EAccount *account; - CamelURL *url = NULL; - - /* XXX EIterator misuses const. */ - account = (EAccount *) e_iterator_get (iterator); - - if (account->source->url != NULL) - url = camel_url_new (account->source->url, NULL); - - if (url != NULL) { - em_rename_camel_url_params (url); - g_free (account->source->url); - account->source->url = camel_url_to_string (url, 0); - camel_url_free (url); - } - - url = NULL; - - if (account->transport->url != NULL) - url = camel_url_new (account->transport->url, NULL); - - if (url != NULL) { - em_rename_camel_url_params (url); - g_free (account->transport->url); - account->transport->url = camel_url_to_string (url, 0); - camel_url_free (url); - } - - e_iterator_next (iterator); - } - - g_object_unref (iterator); - e_account_list_save (account_list); -} - -static gboolean migrate_local_store (EShellBackend *shell_backend) { EMMigrateSession *session; @@ -1101,8 +691,6 @@ migrate_local_store (EShellBackend *shell_backend) camel_session_set_online (CAMEL_SESSION (session), FALSE); migrate_mbox_to_maildir (shell_backend, session); - create_mbox_account (shell_backend, session); - change_sent_and_drafts_local_folders (shell_backend); g_object_unref (session); @@ -1279,10 +867,6 @@ e_mail_migrate (EShellBackend *shell_backend, return emm_setup_initial (data_dir); #ifndef G_OS_WIN32 - if (major < 2 || (major == 2 && minor < 12)) { - em_update_accounts_2_11 (); - } - if (major < 2 || (major == 2 && minor < 22)) em_update_message_notify_settings_2_21 (); @@ -1299,10 +883,6 @@ e_mail_migrate (EShellBackend *shell_backend, em_ensure_proxy_ignore_hosts_being_list (); } - /* Rename account URL parameters to - * match CamelSettings property names. */ - em_rename_account_params (); - if (!migrate_local_store (shell_backend)) return FALSE; diff --git a/mail/e-mail-paned-view.c b/mail/e-mail-paned-view.c index bd76dd967c..29910d8c4a 100644 --- a/mail/e-mail-paned-view.c +++ b/mail/e-mail-paned-view.c @@ -809,6 +809,7 @@ mail_paned_view_update_view_instance (EMailView *view) EShellWindow *shell_window; EShellViewClass *shell_view_class; EShellSettings *shell_settings; + ESourceRegistry *registry; GalViewCollection *view_collection; GalViewInstance *view_instance; CamelFolder *folder; @@ -826,6 +827,7 @@ mail_paned_view_update_view_instance (EMailView *view) shell_window = e_shell_view_get_shell_window (shell_view); shell = e_shell_window_get_shell (shell_window); + registry = e_shell_get_registry (shell); shell_settings = e_shell_get_shell_settings (shell); reader = E_MAIL_READER (view); @@ -844,9 +846,9 @@ mail_paned_view_update_view_instance (EMailView *view) e_filename_make_safe (view_id); outgoing_folder = - em_utils_folder_is_drafts (folder) || - em_utils_folder_is_outbox (folder) || - em_utils_folder_is_sent (folder); + em_utils_folder_is_drafts (registry, folder) || + em_utils_folder_is_outbox (registry, folder) || + em_utils_folder_is_sent (registry, folder); if (e_shell_settings_get_boolean (shell_settings, "mail-global-view-setting")) view_instance = e_shell_view_new_view_instance ( diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c index 6d3f6aafc5..2240523beb 100644 --- a/mail/e-mail-reader-utils.c +++ b/mail/e-mail-reader-utils.c @@ -30,6 +30,7 @@ #include <glib/gi18n.h> #include <libxml/tree.h> #include <gtkhtml/gtkhtml.h> +#include <gconf/gconf-client.h> #include <camel/camel.h> #include "libevolution-utils/e-alert-dialog.h" @@ -358,7 +359,9 @@ copy_tree_state (EMailReader *src_reader, guint e_mail_reader_open_selected (EMailReader *reader) { + EShell *shell; EMailBackend *backend; + ESourceRegistry *registry; CamelFolder *folder; GtkWindow *window; GPtrArray *views; @@ -368,6 +371,9 @@ e_mail_reader_open_selected (EMailReader *reader) g_return_val_if_fail (E_IS_MAIL_READER (reader), 0); backend = e_mail_reader_get_backend (reader); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + registry = e_shell_get_registry (shell); + folder = e_mail_reader_get_folder (reader); uids = e_mail_reader_get_selected_uids (reader); window = e_mail_reader_get_window (reader); @@ -377,9 +383,9 @@ e_mail_reader_open_selected (EMailReader *reader) return 0; } - if (em_utils_folder_is_drafts (folder) || - em_utils_folder_is_outbox (folder) || - em_utils_folder_is_templates (folder)) { + if (em_utils_folder_is_drafts (registry, folder) || + em_utils_folder_is_outbox (registry, folder) || + em_utils_folder_is_templates (registry, folder)) { em_utils_edit_messages (reader, folder, uids, TRUE); return uids->len; } @@ -406,8 +412,8 @@ e_mail_reader_open_selected (EMailReader *reader) CAMEL_VEE_FOLDER (folder), (CamelVeeMessageInfo *) info, &real_uid); - if (em_utils_folder_is_drafts (real_folder) || - em_utils_folder_is_outbox (real_folder)) { + if (em_utils_folder_is_drafts (registry, real_folder) || + em_utils_folder_is_outbox (registry, real_folder)) { GPtrArray *edits; edits = g_ptr_array_new (); @@ -1166,9 +1172,12 @@ void e_mail_reader_create_filter_from_selected (EMailReader *reader, gint filter_type) { + EShell *shell; EActivity *activity; + EMailBackend *backend; AsyncContext *context; GCancellable *cancellable; + ESourceRegistry *registry; CamelFolder *folder; GPtrArray *uids; const gchar *filter_source; @@ -1176,12 +1185,16 @@ e_mail_reader_create_filter_from_selected (EMailReader *reader, g_return_if_fail (E_IS_MAIL_READER (reader)); + backend = e_mail_reader_get_backend (reader); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + registry = e_shell_get_registry (shell); + folder = e_mail_reader_get_folder (reader); g_return_if_fail (CAMEL_IS_FOLDER (folder)); - if (em_utils_folder_is_sent (folder)) + if (em_utils_folder_is_sent (registry, folder)) filter_source = E_FILTER_SOURCE_OUTGOING; - else if (em_utils_folder_is_outbox (folder)) + else if (em_utils_folder_is_outbox (registry, folder)) filter_source = E_FILTER_SOURCE_OUTGOING; else filter_source = E_FILTER_SOURCE_INCOMING; diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c index 7fb29acf40..1bd80b20d5 100644 --- a/mail/e-mail-reader.c +++ b/mail/e-mail-reader.c @@ -28,6 +28,8 @@ #include <glib/gi18n.h> #include <gdk/gdkkeysyms.h> +#include <libedataserver/e-source-mail-account.h> + #ifdef HAVE_XFREE #include <X11/XF86keysym.h> #endif @@ -39,7 +41,6 @@ #include "widgets/misc/e-popup-action.h" #include "widgets/misc/e-menu-tool-action.h" -#include "libemail-utils/e-account-utils.h" #include "libemail-utils/mail-mt.h" #include "libemail-engine/mail-ops.h" @@ -892,6 +893,9 @@ static void action_mail_message_edit_cb (GtkAction *action, EMailReader *reader) { + EShell *shell; + EMailBackend *backend; + ESourceRegistry *registry; CamelFolder *folder; GPtrArray *uids; gboolean replace; @@ -900,11 +904,15 @@ action_mail_message_edit_cb (GtkAction *action, uids = e_mail_reader_get_selected_uids (reader); g_return_if_fail (uids != NULL); + backend = e_mail_reader_get_backend (reader); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + registry = e_shell_get_registry (shell); + /* XXX Either e_mail_reader_get_selected_uids() * or MessageList should do this itself. */ g_ptr_array_set_free_func (uids, (GDestroyNotify) g_free); - replace = em_utils_folder_is_drafts (folder); + replace = em_utils_folder_is_drafts (registry, folder); em_utils_edit_messages (reader, folder, uids, replace); g_ptr_array_unref (uids); @@ -3027,6 +3035,7 @@ mail_reader_set_folder (EMailReader *reader, EMailReaderPrivate *priv; EMailDisplay *display; CamelFolder *previous_folder; + ESourceRegistry *registry; GtkWidget *message_list; EMailBackend *backend; EShell *shell; @@ -3040,7 +3049,9 @@ mail_reader_set_folder (EMailReader *reader, previous_folder = e_mail_reader_get_folder (reader); + backend = e_mail_reader_get_backend (reader); shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + registry = e_shell_get_registry (shell); /* Only synchronize the real folder if we're online. */ if (previous_folder != NULL && (CAMEL_IS_VEE_FOLDER (previous_folder) || e_shell_get_online (shell))) @@ -3051,9 +3062,9 @@ mail_reader_set_folder (EMailReader *reader, return; outgoing = folder != NULL && ( - em_utils_folder_is_drafts (folder) || - em_utils_folder_is_outbox (folder) || - em_utils_folder_is_sent (folder)); + em_utils_folder_is_drafts (registry, folder) || + em_utils_folder_is_outbox (registry, folder) || + em_utils_folder_is_sent (registry, folder)); e_web_view_clear (E_WEB_VIEW (display)); @@ -4171,9 +4182,14 @@ e_mail_reader_changed (EMailReader *reader) guint32 e_mail_reader_check_state (EMailReader *reader) { + EShell *shell; GPtrArray *uids; CamelFolder *folder; CamelStore *store = NULL; + EMailBackend *backend; + ESourceRegistry *registry; + GList *list, *iter; + const gchar *extension_name; const gchar *tag; gboolean can_clear_flags = FALSE; gboolean can_flag_completed = FALSE; @@ -4187,6 +4203,7 @@ e_mail_reader_check_state (EMailReader *reader) gboolean has_undeleted = FALSE; gboolean has_unimportant = FALSE; gboolean has_unread = FALSE; + gboolean have_enabled_account = FALSE; gboolean drafts_or_outbox = FALSE; gboolean store_supports_vjunk = FALSE; gboolean is_mailing_list; @@ -4196,6 +4213,10 @@ e_mail_reader_check_state (EMailReader *reader) g_return_val_if_fail (E_IS_MAIL_READER (reader), 0); + backend = e_mail_reader_get_backend (reader); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + registry = e_shell_get_registry (shell); + folder = e_mail_reader_get_folder (reader); uids = e_mail_reader_get_selected_uids (reader); @@ -4205,8 +4226,8 @@ e_mail_reader_check_state (EMailReader *reader) is_junk_folder = (folder->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0; drafts_or_outbox = - em_utils_folder_is_drafts (folder) || - em_utils_folder_is_outbox (folder); + em_utils_folder_is_drafts (registry, folder) || + em_utils_folder_is_outbox (registry, folder); } /* Initialize this flag based on whether there are any @@ -4291,7 +4312,21 @@ e_mail_reader_check_state (EMailReader *reader) camel_folder_free_message_info (folder, info); } - if (e_get_any_enabled_account () != NULL) + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + list = e_source_registry_list_sources (registry, extension_name); + + for (iter = list; iter != NULL; iter = g_list_next (iter)) { + ESource *source = E_SOURCE (iter->data); + + if (e_source_get_enabled (source)) { + have_enabled_account = TRUE; + break; + } + } + + g_list_free_full (list, (GDestroyNotify) g_object_unref); + + if (have_enabled_account) state |= E_MAIL_READER_HAVE_ENABLED_ACCOUNT; if (uids->len == 1) state |= E_MAIL_READER_SELECTION_SINGLE; diff --git a/mail/e-mail-ui-session.c b/mail/e-mail-ui-session.c index 1d3858d166..f5f5bddf3b 100644 --- a/mail/e-mail-ui-session.c +++ b/mail/e-mail-ui-session.c @@ -44,13 +44,13 @@ #include <libedataserver/e-flag.h> #include <libedataserver/e-proxy.h> +#include <libedataserver/e-source-mail-account.h> #include <libebackend/e-extensible.h> #include <libedataserverui/e-passwords.h> #include "e-mail-account-store.h" #include "e-util/e-util.h" -#include "libemail-utils/e-account-utils.h" #include "libevolution-utils/e-alert-dialog.h" #include "e-util/e-util-private.h" @@ -82,11 +82,11 @@ typedef struct _SourceContext SourceContext; struct _EMailUISessionPrivate { FILE *filter_logfile; + ESourceRegistry *registry; EMailAccountStore *account_store; EMailLabelListStore *label_store; - EAccountList *account_list; - gulong account_changed_handler_id; + gulong source_changed_handler_id; }; enum { @@ -475,62 +475,28 @@ source_context_free (SourceContext *context) } static void -mail_ui_session_dispose (GObject *object) -{ - EMailUISessionPrivate *priv; - - priv = E_MAIL_UI_SESSION_GET_PRIVATE (object); - - if (priv->account_store != NULL) { - e_mail_account_store_clear (priv->account_store); - g_object_unref (priv->account_store); - priv->account_store = NULL; - } - - if (priv->label_store != NULL) { - g_object_unref (priv->label_store); - priv->label_store = NULL; - } - - if (priv->account_list != NULL) { - g_signal_handler_disconnect ( - priv->account_list, - priv->account_changed_handler_id); - g_object_unref (priv->account_list); - priv->account_list = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_mail_ui_session_parent_class)->dispose (object); -} - -static void -mail_ui_session_account_changed_cb (EAccountList *account_list, - EAccount *account, - EMailSession *session) +mail_ui_session_source_changed_cb (ESourceRegistry *registry, + ESource *source, + EMailSession *session) { EMFolderTreeModel *folder_tree_model; CamelService *service; + const gchar *extension_name; + const gchar *uid; - service = camel_session_get_service ( - CAMEL_SESSION (session), account->uid); + uid = e_source_get_uid (source); - if (!CAMEL_IS_STORE (service)) + /* We're only interested in mail account data sources. */ + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + if (!e_source_has_extension (source, extension_name)) return; - /* Update the display name of the corresponding CamelStore. - * EMailAccountStore listens for "notify" signals from each - * service so it will detect this and update the model. - * - * XXX If EAccount defined GObject properties we could just - * bind EAccount:name to CamelService:display-name and - * be done with it. Oh well. - */ - - camel_service_set_display_name (service, account->name); + /* There should be a CamelStore with the same UID. */ + service = camel_session_get_service (CAMEL_SESSION (session), uid); + g_return_if_fail (CAMEL_IS_STORE (service)); /* Remove the store from the folder tree model and, if the - * account is still enabled, re-add it. Easier than trying + * source is still enabled, re-add it. Easier than trying * to update the model with the store in place. * * em_folder_tree_model_add_store() already knows which types @@ -542,34 +508,76 @@ mail_ui_session_account_changed_cb (EAccountList *account_list, em_folder_tree_model_remove_store ( folder_tree_model, CAMEL_STORE (service)); - if (account->enabled) + if (e_source_get_enabled (source)) em_folder_tree_model_add_store ( folder_tree_model, CAMEL_STORE (service)); } static gboolean -mail_ui_session_initialize_stores_idle (gpointer user_data) +mail_ui_session_add_service_cb (SourceContext *context) { - EMailUISession *session = user_data; - EMailAccountStore *account_store; - EAccount *account; + EMailAccountStore *store; + + /* The CamelService should be fully initialized by now. */ + store = e_mail_ui_session_get_account_store (context->session); + e_mail_account_store_add_service (store, context->service); + + return FALSE; +} + +static void +mail_ui_session_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT_STORE: + g_value_set_object ( + value, + e_mail_ui_session_get_account_store ( + E_MAIL_UI_SESSION (object))); + return; + + case PROP_LABEL_STORE: + g_value_set_object ( + value, + e_mail_ui_session_get_label_store ( + E_MAIL_UI_SESSION (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - g_return_val_if_fail (session != NULL, FALSE); +static void +mail_ui_session_dispose (GObject *object) +{ + EMailUISessionPrivate *priv; - account_store = e_mail_ui_session_get_account_store (session); + priv = E_MAIL_UI_SESSION_GET_PRIVATE (object); - /* Initialize which account is default. */ - account = e_get_default_account (); - if (account != NULL) { - CamelService *service; + if (priv->registry != NULL) { + g_signal_handler_disconnect ( + priv->registry, + priv->source_changed_handler_id); + g_object_unref (priv->registry); + priv->registry = NULL; + } - service = camel_session_get_service ( - CAMEL_SESSION (session), account->uid); - e_mail_account_store_set_default_service ( - account_store, service); + if (priv->account_store != NULL) { + e_mail_account_store_clear (priv->account_store); + g_object_unref (priv->account_store); + priv->account_store = NULL; } - return FALSE; + if (priv->label_store != NULL) { + g_object_unref (priv->label_store); + priv->label_store = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_ui_session_parent_class)->dispose (object); } static void @@ -577,19 +585,19 @@ mail_ui_session_constructed (GObject *object) { EMailUISessionPrivate *priv; EMFolderTreeModel *folder_tree_model; + ESourceRegistry *registry; EMailSession *session; - EMailUISession *uisession; - EAccountList *account_list; gulong handler_id; session = E_MAIL_SESSION (object); - uisession = E_MAIL_UI_SESSION (object); - uisession->priv = priv = E_MAIL_UI_SESSION_GET_PRIVATE (object); + priv = E_MAIL_UI_SESSION_GET_PRIVATE (object); priv->account_store = e_mail_account_store_new (session); - account_list = e_get_account_list (); - uisession->priv->account_list = g_object_ref (account_list); + /* Keep our own reference to the ESourceRegistry so we + * can easily disconnect signal handlers in dispose(). */ + registry = e_mail_session_get_registry (session); + priv->registry = g_object_ref (registry); /* XXX Make sure the folder tree model is created before we * add built-in CamelStores so it gets signals from the @@ -601,19 +609,62 @@ mail_ui_session_constructed (GObject *object) * FIXME EMailSession should just own the default instance. */ folder_tree_model = em_folder_tree_model_get_default (); + em_folder_tree_model_set_session (folder_tree_model, session); /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_ui_session_parent_class)->constructed (object); - em_folder_tree_model_set_session (folder_tree_model, session); - - g_idle_add (mail_ui_session_initialize_stores_idle, object); + /* Listen for registry changes. */ handler_id = g_signal_connect ( - account_list, "account-changed", - G_CALLBACK (mail_ui_session_account_changed_cb), session); - priv->account_changed_handler_id = handler_id; + registry, "source-changed", + G_CALLBACK (mail_ui_session_source_changed_cb), session); + priv->source_changed_handler_id = handler_id; +} +static CamelService * +mail_ui_session_add_service (CamelSession *session, + const gchar *uid, + const gchar *protocol, + CamelProviderType type, + GError **error) +{ + CamelService *service; + + /* Chain up to parent's constructed() method. */ + service = CAMEL_SESSION_CLASS (e_mail_ui_session_parent_class)-> + add_service (session, uid, protocol, type, error); + + /* Inform the EMailAccountStore of the new CamelService + * from an idle callback so the service has a chance to + * fully initialize first. */ + if (CAMEL_IS_STORE (service)) { + SourceContext *context; + + context = g_slice_new0 (SourceContext); + context->session = g_object_ref (session); + context->service = g_object_ref (service); + + g_idle_add_full ( + G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc) mail_ui_session_add_service_cb, + context, (GDestroyNotify) source_context_free); + } + + return service; +} + +static void +mail_ui_session_remove_service (CamelSession *session, + CamelService *service) +{ + EMailAccountStore *store; + EMailUISession *ui_session; + + /* Passing a NULL parent window skips confirmation prompts. */ + ui_session = E_MAIL_UI_SESSION (session); + store = e_mail_ui_session_get_account_store (ui_session); + e_mail_account_store_remove_service (store, NULL, service); } static gint @@ -659,8 +710,8 @@ mail_ui_session_alert_user (CamelSession *session, static CamelFilterDriver * mail_ui_session_get_filter_driver (CamelSession *session, - const gchar *type, - GError **error) + const gchar *type, + GError **error) { return (CamelFilterDriver *) mail_call_main ( MAIL_CALL_p_ppp, (MailMainFunc) main_get_filter_driver, @@ -668,80 +719,14 @@ mail_ui_session_get_filter_driver (CamelSession *session, } static void -mail_ui_session_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +mail_ui_session_refresh_service (EMailSession *session, + CamelService *service) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} + g_debug ("*** Refreshing %s ***", + camel_service_get_display_name (service)); -static void -mail_ui_session_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ACCOUNT_STORE: - g_value_set_object ( - value, - e_mail_ui_session_get_account_store ( - E_MAIL_UI_SESSION (object))); - return; - - case PROP_LABEL_STORE: - g_value_set_object ( - value, - e_mail_ui_session_get_label_store ( - E_MAIL_UI_SESSION (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static gboolean -mail_ui_session_add_service_cb (SourceContext *context) -{ - EMailAccountStore *store; - - store = e_mail_ui_session_get_account_store (context->session); - e_mail_account_store_add_service (store, context->service); - - return FALSE; -} - -static CamelService * -mail_ui_session_add_service (CamelSession *session, - const gchar *uid, - const gchar *protocol, - CamelProviderType type, - GError **error) -{ - CamelService *service; - - /* Chain up to parent's constructed() method. */ - service = CAMEL_SESSION_CLASS (e_mail_ui_session_parent_class)-> - add_service (session, uid, protocol, type, error); - - /* Inform the EMailAccountStore of the new CamelService - * from an idle callback so the service has a chance to - * fully initialize first. */ - if (CAMEL_IS_STORE (service)) { - SourceContext *context; - - context = g_slice_new0 (SourceContext); - context->session = g_object_ref (session); - context->service = g_object_ref (service); - - g_idle_add_full ( - G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc) mail_ui_session_add_service_cb, - context, (GDestroyNotify) source_context_free); - } - - return service; + if (camel_session_get_online (CAMEL_SESSION (session))) + mail_receive_service (service); } static EMVFolderContext * @@ -755,23 +740,24 @@ e_mail_ui_session_class_init (EMailUISessionClass *class) { GObjectClass *object_class; CamelSessionClass *session_class; - EMailSessionClass *emailsession_class; + EMailSessionClass *mail_session_class; g_type_class_add_private (class, sizeof (EMailUISessionPrivate)); object_class = G_OBJECT_CLASS (class); - object_class->set_property = mail_ui_session_set_property; object_class->get_property = mail_ui_session_get_property; object_class->dispose = mail_ui_session_dispose; object_class->constructed = mail_ui_session_constructed; session_class = CAMEL_SESSION_CLASS (class); + session_class->add_service = mail_ui_session_add_service; + session_class->remove_service = mail_ui_session_remove_service; session_class->alert_user = mail_ui_session_alert_user; session_class->get_filter_driver = mail_ui_session_get_filter_driver; - session_class->add_service = mail_ui_session_add_service; - emailsession_class = E_MAIL_SESSION_CLASS (class); - emailsession_class->create_vfolder_context = mail_ui_session_create_vfolder_context; + mail_session_class = E_MAIL_SESSION_CLASS (class); + mail_session_class->create_vfolder_context = mail_ui_session_create_vfolder_context; + mail_session_class->refresh_service = mail_ui_session_refresh_service; g_object_class_install_property ( object_class, @@ -803,16 +789,19 @@ e_mail_ui_session_init (EMailUISession *session) } EMailSession * -e_mail_ui_session_new (void) +e_mail_ui_session_new (ESourceRegistry *registry) { const gchar *user_data_dir; const gchar *user_cache_dir; + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + user_data_dir = mail_session_get_data_dir (); user_cache_dir = mail_session_get_cache_dir (); return g_object_new ( E_TYPE_MAIL_UI_SESSION, + "registry", registry, "user-data-dir", user_data_dir, "user-cache-dir", user_cache_dir, NULL); diff --git a/mail/e-mail-ui-session.h b/mail/e-mail-ui-session.h index 7efb472590..ebab600cdb 100644 --- a/mail/e-mail-ui-session.h +++ b/mail/e-mail-ui-session.h @@ -76,7 +76,7 @@ struct _EMailUISessionClass { }; GType e_mail_ui_session_get_type (void); -EMailSession * e_mail_ui_session_new (void); +EMailSession * e_mail_ui_session_new (ESourceRegistry *registry); EMailAccountStore * e_mail_ui_session_get_account_store (EMailUISession *session); diff --git a/mail/e-mail.h b/mail/e-mail.h index 3b0d02dcab..694b8e384b 100644 --- a/mail/e-mail.h +++ b/mail/e-mail.h @@ -20,6 +20,7 @@ #define E_MAIL_H #include <mail/e-mail-attachment-bar.h> +#include <mail/e-mail-authenticator.h> #include <mail/e-mail-backend.h> #include <mail/e-mail-browser.h> #include <mail/e-mail-display.h> diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c deleted file mode 100644 index 8919c0cef4..0000000000 --- a/mail/em-account-editor.c +++ /dev/null @@ -1,5834 +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: - * Dan Winship <danw@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* - * work before merge can occur: - * - * verify behaviour. - * work out what to do with the startup assistant. - * - * also need to work out: - * how to remove unecessary items from a service url once - * configured (removing settings from other types). - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib/gi18n.h> -#include <glib/gstdio.h> - -#include <string.h> -#include <stdarg.h> - -#include <libedataserverui/e-client-utils.h> -#include <libedataserverui/e-passwords.h> - -#include <shell/e-shell.h> - -#include <e-util/e-util.h> -#include <libevolution-utils/e-alert-dialog.h> -#include <e-util/e-dialog-utils.h> -#include <e-util/e-util-private.h> - -#include <libemail-utils/e-account-utils.h> -#include <libemail-utils/e-signature-list.h> -#include <libemail-utils/e-signature-utils.h> -#include <libemail-utils/mail-mt.h> - -#include <libemail-engine/e-mail-folder-utils.h> -#include <libemail-engine/mail-ops.h> - -#include <widgets/misc/e-auth-combo-box.h> -#include <widgets/misc/e-signature-editor.h> -#include <widgets/misc/e-port-entry.h> - -#include "e-mail-account-store.h" -#include "e-mail-backend.h" -#include "e-mail-junk-options.h" -#include "e-mail-ui-session.h" -#include "em-account-editor.h" -#include "em-config.h" -#include "em-folder-selection-button.h" -#include "em-utils.h" -#include "mail-guess-servers.h" -#include "mail-send-recv.h" - -#if defined (HAVE_NSS) && defined (ENABLE_SMIME) -#include <smime/gui/e-cert-selector.h> -#endif - -#define EM_ACCOUNT_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), EM_TYPE_ACCOUNT_EDITOR, EMAccountEditorPrivate)) - -/* Option widgets whose sensitivity depends on another widget, such - * as a checkbox being active, are indented to the right slightly for - * better visual clarity. This specifies how far to the right. */ -#define INDENT_MARGIN 24 - -#define EM_ACCOUNT_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), EM_TYPE_ACCOUNT_EDITOR, EMAccountEditorPrivate)) - -#define d(x) - -/* econfig item for the extra config hings */ -struct _receive_options_item { - EMConfigItem item; - - /* Only CAMEL_PROVIDER_CONF_ENTRYs GtkEntrys are stored here. - * The auto-detect camel provider code will probably be removed */ - GHashTable *extra_table; -}; - -typedef struct _EMAccountEditorService { - EMAccountEditor *emae; /* parent pointer, for callbacks */ - - /* NOTE: keep all widgets together, first frame last check_dialog */ - GtkWidget *frame; - GtkWidget *container; - - GtkComboBox *providers; - - GtkLabel *description; - GtkLabel *hostlabel; - GtkEntry *hostname; - GtkLabel *portlabel; - EPortEntry *port; - GtkLabel *userlabel; - GtkEntry *username; - GtkLabel *pathlabel; - GtkWidget *pathentry; - - GtkWidget *ssl_frame; - GtkComboBox *use_ssl; - GtkWidget *ssl_hbox; - GtkWidget *no_ssl; - - GtkWidget *auth_frame; - GtkComboBox *authtype; - - GtkWidget *authitem; - GtkToggleButton *remember; - GtkButton *check_supported; - GtkToggleButton *needs_auth; - gboolean requires_auth; - - GCancellable *checking; - GtkWidget *check_dialog; - - const gchar *protocol; - CamelProviderType type; - CamelSettings *settings; - - gboolean visible_auth; - gboolean visible_host; - gboolean visible_path; - gboolean visible_port; - gboolean visible_user; -} EMAccountEditorService; - -struct _EMAccountEditorPrivate { - - EMailBackend *backend; - EAccount *modified_account; - EAccount *original_account; - gboolean new_account; - - struct _EMConfig *config; - GList *providers; - - /* signatures */ - GtkComboBox *signatures_dropdown; - guint sig_added_id; - guint sig_removed_id; - guint sig_changed_id; - const gchar *sig_uid; - - /* incoming mail */ - EMAccountEditorService source; - - /* extra incoming config */ - CamelProvider *extra_provider; - GSList *extra_items; /* this is freed by the econfig automatically */ - - /* outgoing mail */ - EMAccountEditorService transport; - - /* account management */ - GtkEntry *identity_entries[5]; - GtkToggleButton *default_account; - GtkWidget *management_frame; - - /* special folders */ - GtkButton *drafts_folder_button; - GtkButton *sent_folder_button; - GtkToggleButton *trash_folder_check; - GtkButton *trash_folder_button; - GtkToggleButton *junk_folder_check; - GtkButton *junk_folder_button; - GtkButton *restore_folders_button; - - /* Security */ - GtkEntry *pgp_key; - GtkToggleButton *pgp_encrypt_to_self; - GtkToggleButton *pgp_always_sign; - GtkToggleButton *pgp_no_imip_sign; - GtkToggleButton *pgp_always_trust; - - GtkToggleButton *smime_sign_default; - GtkEntry *smime_sign_key; - GtkButton *smime_sign_key_select; - GtkButton *smime_sign_key_clear; - GtkButton *smime_sign_select; - GtkToggleButton *smime_encrypt_default; - GtkToggleButton *smime_encrypt_to_self; - GtkEntry *smime_encrypt_key; - GtkButton *smime_encrypt_key_select; - GtkButton *smime_encrypt_key_clear; - - /* Review */ - GtkLabel *review_name; - GtkLabel *review_email; - GtkLabel *send_name; - GtkLabel *send_stype; - GtkLabel *send_saddress; - GtkLabel *send_encryption; - GtkLabel *receive_name; - GtkLabel *receive_stype; - GtkLabel *receive_saddress; - GtkLabel *receive_encryption; - GtkWidget *review_box; - - /* google and yahoo specific data*/ - gboolean is_gmail; - gboolean is_yahoo; - - GtkWidget *calendar; - GtkWidget *tasks; - GtkWidget *gcontacts; - GtkWidget *info_label; - - GtkWidget *account_label; - GtkWidget *gmail_link; - GtkWidget *yahoo_cal_box; - GtkWidget *yahoo_cal_entry; - - /* for e-config callbacks, each page sets up its widgets, then they are dealed out by the get_widget callback in order*/ - GHashTable *widgets; - - /* for assistant page preparation */ - guint identity_set : 1; - guint receive_set : 1; - guint receive_opt_set : 1; - guint send_set : 1; - guint review_set : 1; - - ServerData *selected_server; -}; - -enum { - PROP_0, - PROP_BACKEND, - PROP_MODIFIED_ACCOUNT, - PROP_ORIGINAL_ACCOUNT, - PROP_STORE_PROVIDER, - PROP_STORE_REQUIRES_AUTH, - PROP_STORE_SETTINGS, - PROP_STORE_VISIBLE_AUTH, - PROP_STORE_VISIBLE_HOST, - PROP_STORE_VISIBLE_PATH, - PROP_STORE_VISIBLE_PORT, - PROP_STORE_VISIBLE_USER, - PROP_TRANSPORT_PROVIDER, - PROP_TRANSPORT_REQUIRES_AUTH, - PROP_TRANSPORT_SETTINGS, - PROP_TRANSPORT_VISIBLE_AUTH, - PROP_TRANSPORT_VISIBLE_HOST, - PROP_TRANSPORT_VISIBLE_PATH, - PROP_TRANSPORT_VISIBLE_PORT, - PROP_TRANSPORT_VISIBLE_USER -}; - -static void em_account_editor_construct (EMAccountEditor *emae, EMAccountEditorType type, const gchar *id); -static void emae_account_folder_changed (EMFolderSelectionButton *folder, EMAccountEditor *emae); - -G_DEFINE_TYPE (EMAccountEditor, em_account_editor, G_TYPE_OBJECT) - -static void -emae_config_gone_cb (gpointer pemae, - GObject *pconfig) -{ - EMAccountEditor *emae = pemae; - struct _EMConfig *config = (struct _EMConfig *) pconfig; - - if (!emae) - return; - - if (emae->config == config) - emae->config = NULL; - - if (emae->priv && emae->priv->config == config) - emae->priv->config = NULL; -} - -static void -emae_config_target_changed_cb (EMAccountEditor *emae) -{ - e_config_target_changed ( - (EConfig *) emae->config, - E_CONFIG_TARGET_CHANGED_STATE); -} - -static gint -emae_provider_compare (const CamelProvider *p1, - const CamelProvider *p2) -{ - /* The "none" provider comes first. */ - if (g_strcmp0 (p1->protocol, "none") == 0) - return -1; - if (g_strcmp0 (p2->protocol, "none") == 0) - return 1; - - /* Then sort remote providers before local providers. */ - if (p1->flags & CAMEL_PROVIDER_IS_REMOTE) { - if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) - return 0; - return -1; - } else { - if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) - return 1; - return 0; - } -} - -static GList * -emae_list_providers (void) -{ - GList *list, *link; - GQueue trash = G_QUEUE_INIT; - - list = camel_provider_list (TRUE); - list = g_list_sort (list, (GCompareFunc) emae_provider_compare); - - /* Keep only providers with a "mail" or "news" domain. */ - - for (link = list; link != NULL; link = g_list_next (link)) { - CamelProvider *provider = link->data; - gboolean mail_or_news_domain; - - mail_or_news_domain = - (g_strcmp0 (provider->domain, "mail") == 0) || - (g_strcmp0 (provider->domain, "news") == 0); - - if (mail_or_news_domain) - continue; - - g_queue_push_tail (&trash, link); - } - - while ((link = g_queue_pop_head (&trash)) != NULL) - list = g_list_remove_link (list, link); - - return list; -} - -static void -emae_set_original_account (EMAccountEditor *emae, - EAccount *original_account) -{ - EAccount *modified_account; - - g_return_if_fail (emae->priv->original_account == NULL); - - /* Editing an existing account. */ - if (original_account != NULL) { - gchar *xml; - - xml = e_account_to_xml (original_account); - modified_account = e_account_new_from_xml (xml); - g_free (xml); - - g_object_ref (original_account); - if (emae->type != EMAE_PAGES) - emae->do_signature = TRUE; - - /* thus the emae_setup_service() will pick protocols from the account */ - emae->priv->source.protocol = NULL; - emae->priv->transport.protocol = NULL; - - /* Creating a new account. */ - } else { - modified_account = e_account_new (); - modified_account->enabled = TRUE; - emae->priv->new_account = TRUE; - } - - emae->priv->original_account = original_account; - emae->priv->modified_account = modified_account; -} - -static void -emae_set_backend (EMAccountEditor *emae, - EMailBackend *backend) -{ - g_return_if_fail (E_IS_MAIL_BACKEND (backend)); - g_return_if_fail (emae->priv->backend == NULL); - - emae->priv->backend = g_object_ref (backend); -} - -static CamelProvider * -emae_get_store_provider (EMAccountEditor *emae) -{ - CamelProvider *provider = NULL; - const gchar *protocol; - - protocol = emae->priv->source.protocol; - - if (protocol != NULL) - provider = camel_provider_get (protocol, NULL); - - return provider; -} - -static gboolean -emae_get_store_requires_auth (EMAccountEditor *emae) -{ - return emae->priv->source.requires_auth; -} - -static void -emae_set_store_requires_auth (EMAccountEditor *emae, - gboolean requires_auth) -{ - emae->priv->source.requires_auth = requires_auth; - - g_object_notify (G_OBJECT (emae), "store-requires-auth"); -} - -static CamelSettings * -emae_get_store_settings (EMAccountEditor *emae) -{ - return emae->priv->source.settings; -} - -static void -emae_set_store_settings (EMAccountEditor *emae, - CamelSettings *settings) -{ - if (settings != NULL) - g_object_ref (settings); - - if (emae->priv->source.settings != NULL) { - g_signal_handlers_disconnect_by_func ( - emae->priv->source.settings, - emae_config_target_changed_cb, emae); - g_object_unref (emae->priv->source.settings); - } - - emae->priv->source.settings = settings; - - g_object_notify (G_OBJECT (emae), "store-settings"); -} - -static gboolean -emae_get_store_visible_auth (EMAccountEditor *emae) -{ - return emae->priv->source.visible_auth; -} - -static void -emae_set_store_visible_auth (EMAccountEditor *emae, - gboolean visible_auth) -{ - emae->priv->source.visible_auth = visible_auth; - - g_object_notify (G_OBJECT (emae), "store-visible-auth"); -} - -static gboolean -emae_get_store_visible_host (EMAccountEditor *emae) -{ - return emae->priv->source.visible_host; -} - -static void -emae_set_store_visible_host (EMAccountEditor *emae, - gboolean visible_host) -{ - emae->priv->source.visible_host = visible_host; - - g_object_notify (G_OBJECT (emae), "store-visible-host"); -} - -static gboolean -emae_get_store_visible_path (EMAccountEditor *emae) -{ - return emae->priv->source.visible_path; -} - -static void -emae_set_store_visible_path (EMAccountEditor *emae, - gboolean visible_path) -{ - emae->priv->source.visible_path = visible_path; - - g_object_notify (G_OBJECT (emae), "store-visible-path"); -} - -static gboolean -emae_get_store_visible_port (EMAccountEditor *emae) -{ - return emae->priv->source.visible_port; -} - -static void -emae_set_store_visible_port (EMAccountEditor *emae, - gboolean visible_port) -{ - emae->priv->source.visible_port = visible_port; - - g_object_notify (G_OBJECT (emae), "store-visible-port"); -} - -static gboolean -emae_get_store_visible_user (EMAccountEditor *emae) -{ - return emae->priv->source.visible_user; -} - -static void -emae_set_store_visible_user (EMAccountEditor *emae, - gboolean visible_user) -{ - emae->priv->source.visible_user = visible_user; - - g_object_notify (G_OBJECT (emae), "store-visible-user"); -} - -static CamelProvider * -emae_get_transport_provider (EMAccountEditor *emae) -{ - CamelProvider *provider = NULL; - const gchar *protocol; - - protocol = emae->priv->transport.protocol; - - if (protocol != NULL) - provider = camel_provider_get (protocol, NULL); - - return provider; -} - -static gboolean -emae_get_transport_requires_auth (EMAccountEditor *emae) -{ - return emae->priv->transport.requires_auth; -} - -static void -emae_set_transport_requires_auth (EMAccountEditor *emae, - gboolean requires_auth) -{ - emae->priv->transport.requires_auth = requires_auth; - - g_object_notify (G_OBJECT (emae), "transport-requires-auth"); -} - -static CamelSettings * -emae_get_transport_settings (EMAccountEditor *emae) -{ - return emae->priv->transport.settings; -} - -static void -emae_set_transport_settings (EMAccountEditor *emae, - CamelSettings *settings) -{ - if (settings != NULL) - g_object_ref (settings); - - if (emae->priv->transport.settings != NULL) { - g_signal_handlers_disconnect_by_func ( - emae->priv->transport.settings, - emae_config_target_changed_cb, emae); - g_object_unref (emae->priv->transport.settings); - } - - emae->priv->transport.settings = settings; - - g_object_notify (G_OBJECT (emae), "transport-settings"); -} - -static gboolean -emae_get_transport_visible_auth (EMAccountEditor *emae) -{ - return emae->priv->transport.visible_auth; -} - -static void -emae_set_transport_visible_auth (EMAccountEditor *emae, - gboolean visible_auth) -{ - emae->priv->transport.visible_auth = visible_auth; - - g_object_notify (G_OBJECT (emae), "transport-visible-auth"); -} - -static gboolean -emae_get_transport_visible_host (EMAccountEditor *emae) -{ - return emae->priv->transport.visible_host; -} - -static void -emae_set_transport_visible_host (EMAccountEditor *emae, - gboolean visible_host) -{ - emae->priv->transport.visible_host = visible_host; - - g_object_notify (G_OBJECT (emae), "transport-visible-host"); -} - -static gboolean -emae_get_transport_visible_path (EMAccountEditor *emae) -{ - return emae->priv->transport.visible_path; -} - -static void -emae_set_transport_visible_path (EMAccountEditor *emae, - gboolean visible_path) -{ - emae->priv->transport.visible_path = visible_path; - - g_object_notify (G_OBJECT (emae), "transport-visible-path"); -} - -static gboolean -emae_get_transport_visible_port (EMAccountEditor *emae) -{ - return emae->priv->transport.visible_port; -} - -static void -emae_set_transport_visible_port (EMAccountEditor *emae, - gboolean visible_port) -{ - emae->priv->transport.visible_port = visible_port; - - g_object_notify (G_OBJECT (emae), "transport-visible-port"); -} - -static gboolean -emae_get_transport_visible_user (EMAccountEditor *emae) -{ - return emae->priv->transport.visible_user; -} - -static void -emae_set_transport_visible_user (EMAccountEditor *emae, - gboolean visible_user) -{ - emae->priv->transport.visible_user = visible_user; - - g_object_notify (G_OBJECT (emae), "transport-visible-user"); -} - -static void -emae_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_BACKEND: - emae_set_backend ( - EM_ACCOUNT_EDITOR (object), - g_value_get_object (value)); - return; - - case PROP_ORIGINAL_ACCOUNT: - emae_set_original_account ( - EM_ACCOUNT_EDITOR (object), - g_value_get_object (value)); - return; - - case PROP_STORE_REQUIRES_AUTH: - emae_set_store_requires_auth ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_STORE_SETTINGS: - emae_set_store_settings ( - EM_ACCOUNT_EDITOR (object), - g_value_get_object (value)); - return; - - case PROP_STORE_VISIBLE_AUTH: - emae_set_store_visible_auth ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_STORE_VISIBLE_HOST: - emae_set_store_visible_host ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_STORE_VISIBLE_PATH: - emae_set_store_visible_path ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_STORE_VISIBLE_PORT: - emae_set_store_visible_port ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_STORE_VISIBLE_USER: - emae_set_store_visible_user ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_TRANSPORT_REQUIRES_AUTH: - emae_set_transport_requires_auth ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_TRANSPORT_SETTINGS: - emae_set_transport_settings ( - EM_ACCOUNT_EDITOR (object), - g_value_get_object (value)); - return; - - case PROP_TRANSPORT_VISIBLE_AUTH: - emae_set_transport_visible_auth ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_TRANSPORT_VISIBLE_HOST: - emae_set_transport_visible_host ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_TRANSPORT_VISIBLE_PATH: - emae_set_transport_visible_path ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_TRANSPORT_VISIBLE_PORT: - emae_set_transport_visible_port ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - - case PROP_TRANSPORT_VISIBLE_USER: - emae_set_transport_visible_user ( - EM_ACCOUNT_EDITOR (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -emae_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_BACKEND: - g_value_set_object ( - value, - em_account_editor_get_backend ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_MODIFIED_ACCOUNT: - g_value_set_object ( - value, - em_account_editor_get_modified_account ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_ORIGINAL_ACCOUNT: - g_value_set_object ( - value, - em_account_editor_get_original_account ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_PROVIDER: - g_value_set_pointer ( - value, - emae_get_store_provider ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_REQUIRES_AUTH: - g_value_set_boolean ( - value, - emae_get_store_requires_auth ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_SETTINGS: - g_value_set_object ( - value, - emae_get_store_settings ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_VISIBLE_AUTH: - g_value_set_boolean ( - value, - emae_get_store_visible_auth ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_VISIBLE_HOST: - g_value_set_boolean ( - value, - emae_get_store_visible_host ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_VISIBLE_PATH: - g_value_set_boolean ( - value, - emae_get_store_visible_path ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_VISIBLE_PORT: - g_value_set_boolean ( - value, - emae_get_store_visible_port ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_STORE_VISIBLE_USER: - g_value_set_boolean ( - value, - emae_get_store_visible_user ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_PROVIDER: - g_value_set_pointer ( - value, - emae_get_transport_provider ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_REQUIRES_AUTH: - g_value_set_boolean ( - value, - emae_get_transport_requires_auth ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_SETTINGS: - g_value_set_object ( - value, - emae_get_transport_settings ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_VISIBLE_AUTH: - g_value_set_boolean ( - value, - emae_get_transport_visible_auth ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_VISIBLE_HOST: - g_value_set_boolean ( - value, - emae_get_transport_visible_host ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_VISIBLE_PATH: - g_value_set_boolean ( - value, - emae_get_transport_visible_path ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_VISIBLE_PORT: - g_value_set_boolean ( - value, - emae_get_transport_visible_port ( - EM_ACCOUNT_EDITOR (object))); - return; - - case PROP_TRANSPORT_VISIBLE_USER: - g_value_set_boolean ( - value, - emae_get_transport_visible_user ( - EM_ACCOUNT_EDITOR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -emae_dispose (GObject *object) -{ - EMAccountEditorPrivate *priv; - - priv = EM_ACCOUNT_EDITOR_GET_PRIVATE (object); - - if (priv->backend != NULL) { - g_object_unref (priv->backend); - priv->backend = NULL; - } - - if (priv->modified_account != NULL) { - g_signal_handlers_disconnect_by_func ( - priv->modified_account, - emae_config_target_changed_cb, object); - g_object_unref (priv->modified_account); - priv->modified_account = NULL; - } - - if (priv->original_account != NULL) { - g_object_unref (priv->original_account); - priv->original_account = NULL; - } - - if (priv->source.settings != NULL) { - g_signal_handlers_disconnect_by_func ( - priv->source.settings, - emae_config_target_changed_cb, object); - g_object_unref (priv->source.settings); - priv->source.settings = NULL; - } - - if (priv->transport.settings != NULL) { - g_signal_handlers_disconnect_by_func ( - priv->transport.settings, - emae_config_target_changed_cb, object); - g_object_unref (priv->transport.settings); - priv->transport.settings = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (em_account_editor_parent_class)->dispose (object); -} - -static void -emae_finalize (GObject *object) -{ - EMAccountEditor *emae = EM_ACCOUNT_EDITOR (object); - EMAccountEditorPrivate *priv = emae->priv; - - if (priv->config) - g_object_weak_unref ((GObject *) priv->config, emae_config_gone_cb, emae); - - if (priv->sig_added_id) { - ESignatureList *signatures; - - signatures = e_get_signature_list (); - g_signal_handler_disconnect (signatures, priv->sig_added_id); - g_signal_handler_disconnect (signatures, priv->sig_removed_id); - g_signal_handler_disconnect (signatures, priv->sig_changed_id); - } - - g_list_free (priv->providers); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (em_account_editor_parent_class)->finalize (object); -} - -static void -emae_constructed (GObject *object) -{ - EMAccountEditor *emae; - - emae = EM_ACCOUNT_EDITOR (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (em_account_editor_parent_class)->constructed (object); - - emae->priv->providers = emae_list_providers (); - - /* Set some defaults on the new account before we get started. */ - if (emae->priv->new_account) { - EMailBackend *backend; - EMailSession *session; - - backend = em_account_editor_get_backend (emae); - session = e_mail_backend_get_session (backend); - - /* Pick local Drafts folder. */ - e_account_set_string ( - emae->priv->modified_account, - E_ACCOUNT_DRAFTS_FOLDER_URI, - e_mail_session_get_local_folder_uri ( - session, E_MAIL_LOCAL_FOLDER_DRAFTS)); - - /* Pick local Sent folder. */ - e_account_set_string ( - emae->priv->modified_account, - E_ACCOUNT_SENT_FOLDER_URI, - e_mail_session_get_local_folder_uri ( - session, E_MAIL_LOCAL_FOLDER_SENT)); - - /* Encrypt to self by default. */ - e_account_set_bool ( - emae->priv->modified_account, - E_ACCOUNT_PGP_ENCRYPT_TO_SELF, TRUE); - e_account_set_bool ( - emae->priv->modified_account, - E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, TRUE); - } - - g_signal_connect_swapped ( - emae->priv->modified_account, "changed", - G_CALLBACK (emae_config_target_changed_cb), emae); -} - -static void -em_account_editor_class_init (EMAccountEditorClass *class) -{ - GObjectClass *object_class; - - g_type_class_add_private (class, sizeof (EMAccountEditorPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = emae_set_property; - object_class->get_property = emae_get_property; - object_class->dispose = emae_dispose; - object_class->finalize = emae_finalize; - object_class->constructed = emae_constructed; - - g_object_class_install_property ( - object_class, - PROP_BACKEND, - g_param_spec_object ( - "backend", - "Mail Backend", - NULL, - E_TYPE_MAIL_BACKEND, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_MODIFIED_ACCOUNT, - g_param_spec_object ( - "modified-account", - "Modified Account", - NULL, - E_TYPE_ACCOUNT, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_ORIGINAL_ACCOUNT, - g_param_spec_object ( - "original-account", - "Original Account", - NULL, - E_TYPE_ACCOUNT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_PROVIDER, - g_param_spec_pointer ( - "store-provider", - "Store Provider", - "CamelProvider for the storage service", - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_REQUIRES_AUTH, - g_param_spec_boolean ( - "store-requires-auth", - "Store Requires Auth", - "Storage service requires authentication", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_SETTINGS, - g_param_spec_object ( - "store-settings", - "Store Settings", - "CamelSettings for the storage service", - CAMEL_TYPE_SETTINGS, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_VISIBLE_AUTH, - g_param_spec_boolean ( - "store-visible-auth", - "Store Visible Auth", - "Show auth widgets for the storage service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_VISIBLE_HOST, - g_param_spec_boolean ( - "store-visible-host", - "Store Visible Host", - "Show host widgets for the storage service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_VISIBLE_PATH, - g_param_spec_boolean ( - "store-visible-path", - "Store Visible Path", - "Show path widgets for the storage service", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_VISIBLE_PORT, - g_param_spec_boolean ( - "store-visible-port", - "Store Visible Port", - "Show port widgets for the storage service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_STORE_VISIBLE_USER, - g_param_spec_boolean ( - "store-visible-user", - "Store Visible User", - "Show user widgets for the storage service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_PROVIDER, - g_param_spec_pointer ( - "transport-provider", - "Transport Provider", - "CamelProvider for the transport service", - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_REQUIRES_AUTH, - g_param_spec_boolean ( - "transport-requires-auth", - "Transport Requires Auth", - "Transport service requires authentication", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_SETTINGS, - g_param_spec_object ( - "transport-settings", - "Transport Settings", - "CamelSettings for the transport service", - CAMEL_TYPE_SETTINGS, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_VISIBLE_AUTH, - g_param_spec_boolean ( - "transport-visible-auth", - "Transport Visible Auth", - "Show auth widgets for the transport service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_VISIBLE_HOST, - g_param_spec_boolean ( - "transport-visible-host", - "Transport Visible Host", - "Show host widgets for the transport service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_VISIBLE_PATH, - g_param_spec_boolean ( - "transport-visible-path", - "Transport Visible Path", - "Show path widgets for the transport service", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_VISIBLE_PORT, - g_param_spec_boolean ( - "transport-visible-port", - "Transport Visible Port", - "Show port widgets for the transport service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property ( - object_class, - PROP_TRANSPORT_VISIBLE_USER, - g_param_spec_boolean ( - "transport-visible-user", - "Transport Visible User", - "Show user widgets for the transport service", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); -} - -static void -em_account_editor_init (EMAccountEditor *emae) -{ - emae->priv = EM_ACCOUNT_EDITOR_GET_PRIVATE (emae); - - emae->priv->selected_server = NULL; - emae->priv->source.emae = emae; - emae->priv->transport.emae = emae; - emae->priv->widgets = g_hash_table_new (g_str_hash, g_str_equal); - - /* Pick default storage and transport protocols. */ - emae->priv->source.protocol = "imapx"; - emae->priv->transport.protocol = "smtp"; - - emae->priv->is_gmail = FALSE; - emae->priv->is_yahoo = FALSE; -} - -/** - * em_account_editor_new: - * @account: - * @type: - * - * Create a new account editor. If @account is NULL then this is to - * create a new account, else @account is copied to a working - * structure and is for editing an existing account. - * - * Return value: - **/ -EMAccountEditor * -em_account_editor_new (EAccount *account, - EMAccountEditorType type, - EMailBackend *backend, - const gchar *id) -{ - EMAccountEditor *emae; - - g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); - - emae = g_object_new ( - EM_TYPE_ACCOUNT_EDITOR, - "original-account", account, - "backend", backend, NULL); - - em_account_editor_construct (emae, type, id); - - return emae; -} - -/** - * em_account_editor_new_for_pages: - * @account: - * @type: - * - * Create a new account editor. If @account is NULL then this is to - * create a new account, else @account is copied to a working - * structure and is for editing an existing account. - * - * Return value: - **/ -EMAccountEditor * -em_account_editor_new_for_pages (EAccount *account, - EMAccountEditorType type, - EMailBackend *backend, - const gchar *id, - GtkWidget **pages) -{ - EMAccountEditor *emae; - - g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); - - emae = g_object_new ( - EM_TYPE_ACCOUNT_EDITOR, - "original-account", account, - "backend", backend, NULL); - - emae->pages = pages; - em_account_editor_construct (emae, type, id); - - return emae; -} - -EMailBackend * -em_account_editor_get_backend (EMAccountEditor *emae) -{ - g_return_val_if_fail (EM_IS_ACCOUNT_EDITOR (emae), NULL); - - return emae->priv->backend; -} - -EAccount * -em_account_editor_get_modified_account (EMAccountEditor *emae) -{ - g_return_val_if_fail (EM_IS_ACCOUNT_EDITOR (emae), NULL); - - return emae->priv->modified_account; -} - -EAccount * -em_account_editor_get_original_account (EMAccountEditor *emae) -{ - g_return_val_if_fail (EM_IS_ACCOUNT_EDITOR (emae), NULL); - - return emae->priv->original_account; -} - -/* ********************************************************************** */ - -static gboolean -is_email (const gchar *address) -{ - /* This is supposed to check if the address's domain could be - * an FQDN but alas, it's not worth the pain and suffering. */ - const gchar *at; - - at = strchr (address, '@'); - /* make sure we have an '@' and that it's not the first or last gchar */ - if (!at || at == address || *(at + 1) == '\0') - return FALSE; - - return TRUE; -} - -static CamelURL * -emae_account_url (EMAccountEditor *emae, - gint urlid) -{ - EAccount *account; - CamelURL *url = NULL; - const gchar *uri; - - account = em_account_editor_get_modified_account (emae); - uri = e_account_get_string (account, urlid); - - /* XXX Stupid hack for these stupid transport-only accounts. - * We've been saving these as invalid URI strings all this - * time; no protocol, just "//...". Catch it and fix it. */ - if (uri != NULL && g_str_has_prefix (uri, "//")) - return camel_url_new ("none:", NULL); - - if (uri != NULL && *uri != '\0') - url = camel_url_new (uri, NULL); - - if (url == NULL) { - url = camel_url_new ("dummy:", NULL); - camel_url_set_protocol (url, NULL); - } - - return url; -} - -/* ********************************************************************** */ - -static void -default_folders_clicked (GtkButton *button, - gpointer user_data) -{ - EMAccountEditor *emae = user_data; - EMFolderSelectionButton *folder_button; - EMailBackend *backend; - EMailSession *session; - const gchar *folder_uri; - - backend = em_account_editor_get_backend (emae); - session = e_mail_backend_get_session (backend); - - folder_button = - EM_FOLDER_SELECTION_BUTTON ( - emae->priv->drafts_folder_button); - folder_uri = e_mail_session_get_local_folder_uri ( - session, E_MAIL_LOCAL_FOLDER_DRAFTS); - em_folder_selection_button_set_folder_uri (folder_button, folder_uri); - emae_account_folder_changed (folder_button, emae); - - folder_button = - EM_FOLDER_SELECTION_BUTTON ( - emae->priv->sent_folder_button); - folder_uri = e_mail_session_get_local_folder_uri ( - session, E_MAIL_LOCAL_FOLDER_SENT); - em_folder_selection_button_set_folder_uri (folder_button, folder_uri); - emae_account_folder_changed (folder_button, emae); - - gtk_toggle_button_set_active (emae->priv->trash_folder_check, FALSE); - gtk_toggle_button_set_active (emae->priv->junk_folder_check, FALSE); -} - -/* The camel provider auto-detect interface should be deprecated. - * But it still needs to be replaced with something of similar functionality. - * Just using the normal econfig plugin mechanism should be adequate. */ -static void -emae_auto_detect_free (gpointer key, - gpointer value, - gpointer user_data) -{ - g_free (key); - g_free (value); -} - -static void -emae_auto_detect (EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - EMAccountEditorService *service = &priv->source; - CamelProvider *provider; - GHashTable *auto_detected; - GSList *l; - CamelProviderConfEntry *entries; - gchar *value; - gint i; - CamelURL *url; - - provider = camel_provider_get (service->protocol, NULL); - - if (provider == NULL || provider->extra_conf == NULL) - return; - - entries = provider->extra_conf; - - d (printf ("Running auto-detect\n")); - - url = emae_account_url (emae, E_ACCOUNT_SOURCE_URL); - camel_provider_auto_detect (provider, url, &auto_detected, NULL); - camel_url_free (url); - - if (auto_detected == NULL) { - d (printf (" no values detected\n")); - return; - } - - for (i = 0; entries[i].type != CAMEL_PROVIDER_CONF_END; i++) { - struct _receive_options_item *item; - GtkWidget *w; - - if (entries[i].name == NULL - || (value = g_hash_table_lookup (auto_detected, entries[i].name)) == NULL) - continue; - - /* only 2 providers use this, and they only do it for 3 entries only */ - g_return_if_fail (entries[i].type == CAMEL_PROVIDER_CONF_ENTRY); - - w = NULL; - for (l = emae->priv->extra_items; l; l = g_slist_next (l)) { - item = l->data; - if (item->extra_table && (w = g_hash_table_lookup (item->extra_table, entries[i].name))) - break; - } - - gtk_entry_set_text ((GtkEntry *)w, value?value:""); - } - - g_hash_table_foreach (auto_detected, emae_auto_detect_free, NULL); - g_hash_table_destroy (auto_detected); -} - -static void -emae_signature_added (ESignatureList *signatures, - ESignature *sig, - EMAccountEditor *emae) -{ - GtkTreeModel *model; - GtkTreeIter iter; - const gchar *name; - const gchar *uid; - - name = e_signature_get_name (sig); - uid = e_signature_get_uid (sig); - - model = gtk_combo_box_get_model (emae->priv->signatures_dropdown); - - gtk_list_store_append ((GtkListStore *) model, &iter); - gtk_list_store_set ((GtkListStore *) model, &iter, 0, name, 1, uid, -1); - - gtk_combo_box_set_active ( - emae->priv->signatures_dropdown, - gtk_tree_model_iter_n_children (model, NULL) - 1); -} - -static gint -emae_signature_get_iter (EMAccountEditor *emae, - ESignature *sig, - GtkTreeModel **modelp, - GtkTreeIter *iter) -{ - GtkTreeModel *model; - gint found = 0; - - model = gtk_combo_box_get_model (emae->priv->signatures_dropdown); - *modelp = model; - if (!gtk_tree_model_get_iter_first (model, iter)) - return FALSE; - - do { - const gchar *signature_uid; - gchar *uid; - - signature_uid = e_signature_get_uid (sig); - - gtk_tree_model_get (model, iter, 1, &uid, -1); - if (uid && !strcmp (uid, signature_uid)) - found = TRUE; - g_free (uid); - } while (!found && gtk_tree_model_iter_next (model, iter)); - - return found; -} - -static void -emae_signature_removed (ESignatureList *signatures, - ESignature *sig, - EMAccountEditor *emae) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - if (emae_signature_get_iter (emae, sig, &model, &iter)) - gtk_list_store_remove ((GtkListStore *) model, &iter); -} - -static void -emae_signature_changed (ESignatureList *signatures, - ESignature *sig, - EMAccountEditor *emae) -{ - GtkTreeIter iter; - GtkTreeModel *model; - const gchar *name; - - name = e_signature_get_name (sig); - - if (emae_signature_get_iter (emae, sig, &model, &iter)) - gtk_list_store_set ((GtkListStore *) model, &iter, 0, name, -1); -} - -static void -emae_signaturetype_changed (GtkComboBox *dropdown, - EMAccountEditor *emae) -{ - EAccount *account; - gint id = gtk_combo_box_get_active (dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - gchar *uid = NULL; - - account = em_account_editor_get_modified_account (emae); - - if (id != -1) { - model = gtk_combo_box_get_model (dropdown); - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) - gtk_tree_model_get (model, &iter, 1, &uid, -1); - } - - e_account_set_string (account, E_ACCOUNT_ID_SIGNATURE, uid); - g_free (uid); -} - -static void -emae_signature_new (GtkWidget *widget, - EMAccountEditor *emae) -{ - GtkWidget *editor; - gpointer parent; - - parent = gtk_widget_get_toplevel (widget); - parent = gtk_widget_is_toplevel (parent) ? parent : NULL; - - editor = e_signature_editor_new (); - gtk_window_set_transient_for (GTK_WINDOW (editor), parent); - gtk_widget_show (editor); -} - -static GtkWidget * -emae_setup_signatures (EMAccountEditor *emae, - GtkBuilder *builder) -{ - EMAccountEditorPrivate *p = emae->priv; - EAccount *account; - GtkComboBox *dropdown = (GtkComboBox *)e_builder_get_widget (builder, "signature_dropdown"); - GtkCellRenderer *cell = gtk_cell_renderer_text_new (); - GtkListStore *store; - gint i, active = 0; - GtkTreeIter iter; - ESignatureList *signatures; - EIterator *it; - const gchar *current; - GtkWidget *button; - - account = em_account_editor_get_modified_account (emae); - current = e_account_get_string (account, E_ACCOUNT_ID_SIGNATURE); - - emae->priv->signatures_dropdown = dropdown; - gtk_widget_show ((GtkWidget *) dropdown); - - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - - gtk_list_store_append (store, &iter); - /* Translators: "None" as an option for a default signature of an account, part of "Signature: None" */ - gtk_list_store_set (store, &iter, 0, C_("mail-signature", "None"), 1, NULL, -1); - - signatures = e_get_signature_list (); - - if (p->sig_added_id == 0) { - p->sig_added_id = g_signal_connect ( - signatures, "signature-added", - G_CALLBACK (emae_signature_added), emae); - p->sig_removed_id = g_signal_connect ( - signatures, "signature-removed", - G_CALLBACK (emae_signature_removed), emae); - p->sig_changed_id = g_signal_connect ( - signatures, "signature-changed", - G_CALLBACK (emae_signature_changed), emae); - } - - /* we need to count the 'none' entry before using the index */ - i = 1; - it = e_list_get_iterator ((EList *) signatures); - while (e_iterator_is_valid (it)) { - ESignature *sig = (ESignature *) e_iterator_get (it); - const gchar *name; - const gchar *uid; - - name = e_signature_get_name (sig); - uid = e_signature_get_uid (sig); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, name, 1, uid, -1); - - if (current && !strcmp (current, uid)) - active = i; - - e_iterator_next (it); - i++; - } - g_object_unref (it); - - gtk_cell_layout_pack_start ((GtkCellLayout *) dropdown, cell, TRUE); - gtk_cell_layout_set_attributes ((GtkCellLayout *)dropdown, cell, "text", 0, NULL); - - gtk_combo_box_set_model (dropdown, (GtkTreeModel *) store); - gtk_combo_box_set_active (dropdown, active); - - g_signal_connect ( - dropdown, "changed", - G_CALLBACK (emae_signaturetype_changed), emae); - - button = e_builder_get_widget (builder, "sigAddNew"); - g_signal_connect ( - button, "clicked", - G_CALLBACK (emae_signature_new), emae); - - return (GtkWidget *) dropdown; -} - -static void -emae_receipt_policy_changed (GtkComboBox *dropdown, - EMAccountEditor *emae) -{ - EAccount *account; - gint id = gtk_combo_box_get_active (dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - EAccountReceiptPolicy policy; - - account = em_account_editor_get_modified_account (emae); - - if (id != -1) { - model = gtk_combo_box_get_model (dropdown); - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) { - gtk_tree_model_get (model, &iter, 1, &policy, -1); - e_account_set_int (account, E_ACCOUNT_RECEIPT_POLICY, policy); - } - } -} - -static GtkWidget * -emae_setup_receipt_policy (EMAccountEditor *emae, - GtkBuilder *builder) -{ - EAccount *account; - GtkComboBox *dropdown = (GtkComboBox *)e_builder_get_widget (builder, "receipt_policy_dropdown"); - GtkListStore *store; - GtkCellRenderer *cell; - gint i = 0, active = 0; - GtkTreeIter iter; - EAccountReceiptPolicy current; - static struct { - EAccountReceiptPolicy policy; - const gchar *label; - } receipt_policies[] = { - { E_ACCOUNT_RECEIPT_NEVER, N_("Never") }, - { E_ACCOUNT_RECEIPT_ALWAYS, N_("Always") }, - { E_ACCOUNT_RECEIPT_ASK, N_("Ask for each message") } - }; - - account = em_account_editor_get_modified_account (emae); - current = account->receipt_policy; - - gtk_widget_show ((GtkWidget *) dropdown); - - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - - for (i = 0; i < 3; ++i) { - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - 0, _(receipt_policies[i].label), - 1, receipt_policies[i].policy, - -1); - if (current == receipt_policies[i].policy) - active = i; - } - - gtk_combo_box_set_model (dropdown, (GtkTreeModel *) store); - - cell = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (dropdown), cell, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (dropdown), cell, "text", 0, NULL); - - gtk_combo_box_set_active (dropdown, active); - - g_signal_connect ( - dropdown, "changed", - G_CALLBACK (emae_receipt_policy_changed), emae); - - return (GtkWidget *) dropdown; -} - -static void -emae_account_entry_changed (GtkEntry *entry, - EMAccountEditor *emae) -{ - EAccount *account; - gchar *text; - gpointer data; - - account = em_account_editor_get_modified_account (emae); - data = g_object_get_data (G_OBJECT (entry), "account-item"); - text = g_strdup (gtk_entry_get_text (entry)); - - g_strstrip (text); - - e_account_set_string (account, GPOINTER_TO_INT (data), text); - - g_free (text); -} - -static GtkEntry * -emae_account_entry (EMAccountEditor *emae, - const gchar *name, - gint item, - GtkBuilder *builder) -{ - EAccount *account; - GtkEntry *entry; - const gchar *text; - - account = em_account_editor_get_modified_account (emae); - entry = (GtkEntry *) e_builder_get_widget (builder, name); - text = e_account_get_string (account, item); - if (text) - gtk_entry_set_text (entry, text); - g_object_set_data ((GObject *)entry, "account-item", GINT_TO_POINTER(item)); - g_signal_connect ( - entry, "changed", - G_CALLBACK (emae_account_entry_changed), emae); - - return entry; -} - -static void -emae_account_toggle_changed (GtkToggleButton *toggle, - EMAccountEditor *emae) -{ - EAccount *account; - gboolean active; - gpointer data; - - account = em_account_editor_get_modified_account (emae); - data = g_object_get_data (G_OBJECT (toggle), "account-item"); - active = gtk_toggle_button_get_active (toggle); - - e_account_set_bool (account, GPOINTER_TO_INT (data), active); -} - -static void -emae_account_toggle_widget (EMAccountEditor *emae, - GtkToggleButton *toggle, - gint item) -{ - EAccount *account; - gboolean active; - - account = em_account_editor_get_modified_account (emae); - - active = e_account_get_bool (account, item); - gtk_toggle_button_set_active (toggle, active); - - g_object_set_data ( - G_OBJECT (toggle), "account-item", - GINT_TO_POINTER (item)); - - g_signal_connect ( - toggle, "toggled", - G_CALLBACK (emae_account_toggle_changed), emae); -} - -static GtkToggleButton * -emae_account_toggle (EMAccountEditor *emae, - const gchar *name, - gint item, - GtkBuilder *builder) -{ - GtkToggleButton *toggle; - - toggle = (GtkToggleButton *) e_builder_get_widget (builder, name); - emae_account_toggle_widget (emae, toggle, item); - - return toggle; -} - -static void -emae_account_spinint_changed (GtkSpinButton *spin, - EMAccountEditor *emae) -{ - EAccount *account; - gpointer data; - gint value; - - account = em_account_editor_get_modified_account (emae); - data = g_object_get_data (G_OBJECT (spin), "account-item"); - value = gtk_spin_button_get_value (spin); - - e_account_set_int (account, GPOINTER_TO_INT (data), value); -} - -static void -emae_account_spinint_widget (EMAccountEditor *emae, - GtkSpinButton *spin, - gint item) -{ - EAccount *account; - gint v_int; - - account = em_account_editor_get_modified_account (emae); - - v_int = e_account_get_int (account, item); - gtk_spin_button_set_value (spin, v_int); - - g_object_set_data ( - G_OBJECT (spin), "account-item", - GINT_TO_POINTER (item)); - - g_signal_connect ( - spin, "value-changed", - G_CALLBACK (emae_account_spinint_changed), emae); -} - -static void -emae_account_folder_changed (EMFolderSelectionButton *folder, - EMAccountEditor *emae) -{ - EAccount *account; - gpointer data; - const gchar *selection; - - account = em_account_editor_get_modified_account (emae); - data = g_object_get_data (G_OBJECT (folder), "account-item"); - selection = em_folder_selection_button_get_folder_uri (folder); - - e_account_set_string (account, GPOINTER_TO_INT (data), selection); -} - -static EMFolderSelectionButton * -emae_account_folder (EMAccountEditor *emae, - const gchar *name, - gint item, - gint deffolder, - GtkBuilder *builder) -{ - EAccount *account; - EMFolderSelectionButton *folder; - EMailBackend *backend; - EMailSession *session; - const gchar *uri; - - account = em_account_editor_get_modified_account (emae); - backend = em_account_editor_get_backend (emae); - session = e_mail_backend_get_session (backend); - - folder = (EMFolderSelectionButton *) e_builder_get_widget (builder, name); - em_folder_selection_button_set_session (folder, session); - - uri = e_account_get_string (account, item); - if (uri != NULL) { - em_folder_selection_button_set_folder_uri (folder, uri); - } else { - uri = e_mail_session_get_local_folder_uri (session, deffolder); - em_folder_selection_button_set_folder_uri (folder, uri); - } - - g_object_set_data ((GObject *)folder, "account-item", GINT_TO_POINTER(item)); - g_object_set_data ((GObject *)folder, "folder-default", GINT_TO_POINTER(deffolder)); - g_signal_connect ( - folder, "selected", - G_CALLBACK (emae_account_folder_changed), emae); - gtk_widget_show ((GtkWidget *) folder); - - return folder; -} - -#if defined (HAVE_NSS) && defined (ENABLE_SMIME) -static void -smime_changed (EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - gint act; - const gchar *tmp; - - tmp = gtk_entry_get_text (priv->smime_sign_key); - act = tmp && tmp[0]; - gtk_widget_set_sensitive ((GtkWidget *) priv->smime_sign_key_clear, act); - gtk_widget_set_sensitive ((GtkWidget *) priv->smime_sign_default, act); - if (!act) - gtk_toggle_button_set_active (priv->smime_sign_default, FALSE); - - tmp = gtk_entry_get_text (priv->smime_encrypt_key); - act = tmp && tmp[0]; - gtk_widget_set_sensitive ((GtkWidget *) priv->smime_encrypt_key_clear, act); - gtk_widget_set_sensitive ((GtkWidget *) priv->smime_encrypt_default, act); - gtk_widget_set_sensitive ((GtkWidget *) priv->smime_encrypt_to_self, act); - if (!act) { - gtk_toggle_button_set_active (priv->smime_encrypt_default, FALSE); - } -} - -static void -smime_sign_key_selected (GtkWidget *dialog, - const gchar *key, - EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - - if (key != NULL) { - gtk_entry_set_text (priv->smime_sign_key, key); - smime_changed (emae); - } - - gtk_widget_destroy (dialog); -} - -static void -smime_sign_key_select (GtkWidget *button, - EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - GtkWidget *w; - - w = e_cert_selector_new (E_CERT_SELECTOR_SIGNER, gtk_entry_get_text (priv->smime_sign_key)); - gtk_window_set_modal ((GtkWindow *) w, TRUE); - gtk_window_set_transient_for ((GtkWindow *) w, (GtkWindow *) gtk_widget_get_toplevel (button)); - g_signal_connect ( - w, "selected", - G_CALLBACK (smime_sign_key_selected), emae); - gtk_widget_show (w); -} - -static void -smime_sign_key_clear (GtkWidget *w, - EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - - gtk_entry_set_text (priv->smime_sign_key, ""); - smime_changed (emae); -} - -static void -smime_encrypt_key_selected (GtkWidget *dialog, - const gchar *key, - EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - - if (key != NULL) { - gtk_entry_set_text (priv->smime_encrypt_key, key); - smime_changed (emae); - } - - gtk_widget_destroy (dialog); -} - -static void -smime_encrypt_key_select (GtkWidget *button, - EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - GtkWidget *w; - - w = e_cert_selector_new (E_CERT_SELECTOR_RECIPIENT, gtk_entry_get_text (priv->smime_encrypt_key)); - gtk_window_set_modal ((GtkWindow *) w, TRUE); - gtk_window_set_transient_for ((GtkWindow *) w, (GtkWindow *) gtk_widget_get_toplevel (button)); - g_signal_connect ( - w, "selected", - G_CALLBACK (smime_encrypt_key_selected), emae); - gtk_widget_show (w); -} - -static void -smime_encrypt_key_clear (GtkWidget *w, - EMAccountEditor *emae) -{ - EMAccountEditorPrivate *priv = emae->priv; - - gtk_entry_set_text (priv->smime_encrypt_key, ""); - smime_changed (emae); -} -#endif - -/* This is used to map each of the two services in a typical account to - * the widgets that represent each service. i.e. the receiving (source) - * service, and the sending (transport) service. It is used throughout - * the following code to drive each page. */ -static struct _service_info { - gint account_uri_key; - gint save_passwd_key; - - const gchar *frame; - const gchar *type_dropdown; - - const gchar *container; - const gchar *description; - const gchar *hostname; - const gchar *hostlabel; - const gchar *port; - const gchar *portlabel; - const gchar *username; - const gchar *userlabel; - const gchar *path; - const gchar *pathlabel; - const gchar *pathentry; - - const gchar *security_frame; - const gchar *ssl_hbox; - const gchar *use_ssl; - const gchar *ssl_disabled; - - const gchar *needs_auth; - const gchar *auth_frame; - - const gchar *authtype; - const gchar *authtype_check; - - const gchar *remember_password; - -} emae_service_info[CAMEL_NUM_PROVIDER_TYPES] = { - - { E_ACCOUNT_SOURCE_URL, - E_ACCOUNT_SOURCE_SAVE_PASSWD, - - "source-config-section", - "source_type_dropdown", - - "vboxSourceBorder", - "source_description", - "source_host", - "source_host_label", - "source_port", - "source_port_label", - "source_user", - "source_user_label", - "source_path", - "source_path_label", - "source_path_entry", - - "source-security-section", - "source_ssl_hbox", - "source_use_ssl", - "source_ssl_disabled", - - NULL, - "source-auth-section", - - "source_auth_dropdown", - "source_check_supported", - - "source_remember_password" - }, - - { E_ACCOUNT_TRANSPORT_URL, - E_ACCOUNT_TRANSPORT_SAVE_PASSWD, - - "transport-server-section", - "transport_type_dropdown", - - "vboxTransportBorder", - "transport_description", - "transport_host", - "transport_host_label", - "transport_port", - "transport_port_label", - "transport_user", - "transport_user_label", - NULL, - NULL, - NULL, - - "transport-security-section", - "transport_ssl_hbox", - "transport_use_ssl", - "transport_ssl_disabled", - - "transport_needs_auth", - "transport-auth-section", - - "transport_auth_dropdown", - "transport_check_supported", - - "transport_remember_password" - } -}; - -static void -emae_file_chooser_changed (GtkFileChooser *file_chooser, - EMAccountEditorService *service) -{ - CamelLocalSettings *local_settings; - const gchar *filename; - - local_settings = CAMEL_LOCAL_SETTINGS (service->settings); - filename = gtk_file_chooser_get_filename (file_chooser); - camel_local_settings_set_path (local_settings, filename); -} - -static void -emae_ensure_auth_mechanism (CamelProvider *provider, - CamelSettings *settings) -{ - CamelServiceAuthType *auth_type; - const gchar *auth_mechanism; - - auth_mechanism = - camel_network_settings_get_auth_mechanism ( - CAMEL_NETWORK_SETTINGS (settings)); - - /* If a mechanism name is already set, we're fine. */ - if (auth_mechanism != NULL) - return; - - /* Check that the CamelProvider defines some auth mechanisms. - * If not, it's reasonable to leave the mechanism name unset. */ - if (provider->authtypes == NULL) - return; - - /* No authentication mechanism has been chosen, so we'll choose - * one from the CamelProvider's list of available mechanisms. */ - - auth_type = provider->authtypes->data; - auth_mechanism = auth_type->authproto; - - camel_network_settings_set_auth_mechanism ( - CAMEL_NETWORK_SETTINGS (settings), auth_mechanism); -} - -static void -emae_setup_settings (EMAccountEditorService *service) -{ - CamelServiceClass *class; - CamelProvider *provider; - CamelSettings *settings = NULL; - GType service_type; - GType settings_type; - CamelURL *url; - - provider = camel_provider_get (service->protocol, NULL); - g_return_if_fail (provider != NULL); - - service_type = provider->object_types[service->type]; - g_return_if_fail (g_type_is_a (service_type, CAMEL_TYPE_SERVICE)); - - class = g_type_class_ref (service_type); - settings_type = class->settings_type; - g_type_class_unref (class); - - url = emae_account_url ( - service->emae, - emae_service_info[service->type].account_uri_key); - - /* Destroy any old CamelSettings instances. - * Changing CamelProviders invalidates them. */ - - if (service->settings != NULL) - camel_settings_save_to_url (service->settings, url); - - if (g_type_is_a (settings_type, CAMEL_TYPE_SETTINGS)) { - settings = g_object_new (settings_type, NULL); - camel_settings_load_from_url (settings, url); - - g_signal_connect_swapped ( - settings, "notify", - G_CALLBACK (emae_config_target_changed_cb), - service->emae); - } - - camel_url_free (url); - - if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) { - emae_set_store_settings (service->emae, settings); - emae_set_transport_settings (service->emae, settings); - - } else if (service->type == CAMEL_PROVIDER_STORE) { - emae_set_store_settings (service->emae, settings); - - } else if (service->type == CAMEL_PROVIDER_TRANSPORT) { - emae_set_transport_settings (service->emae, settings); - } - - if (CAMEL_IS_NETWORK_SETTINGS (settings)) { - CamelNetworkSettings *network_settings; - guint16 port; - - network_settings = CAMEL_NETWORK_SETTINGS (settings); - - /* remember port number as set before binding properties, - * because changes in auth-mechanism combo can reset the port, - * thus effectively lost it, when set to other known value */ - port = camel_network_settings_get_port (network_settings); - - /* Even if the service does not need to authenticate, we - * still need to initialize the auth mechanism combo box. - * So if CamelSettings does not already have a mechanism - * name set, choose one from the CamelProvider's list of - * available auth mechanisms. Later in emae_commit(), - * if need be, we'll revert the setting back to NULL. */ - emae_ensure_auth_mechanism (provider, settings); - - g_object_bind_property ( - settings, "auth-mechanism", - service->authtype, "active-id", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - settings, "host", - service->hostname, "text", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - g_object_bind_property_full ( - settings, "security-method", - service->use_ssl, "active-id", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE, - e_binding_transform_enum_value_to_nick, - e_binding_transform_enum_nick_to_value, - NULL, (GDestroyNotify) NULL); - - g_object_bind_property ( - settings, "port", - service->port, "port", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - settings, "security-method", - service->port, "security-method", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - settings, "user", - service->username, "text", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - /* restore previously saved port, if set */ - if (port > 0) - camel_network_settings_set_port (network_settings, port); - } - - if (CAMEL_IS_LOCAL_SETTINGS (settings)) { - const gchar *path; - - path = camel_local_settings_get_path ( - CAMEL_LOCAL_SETTINGS (settings)); - if (path != NULL && *path != '\0') - gtk_file_chooser_set_filename ( - GTK_FILE_CHOOSER (service->pathentry), path); - } - - g_object_unref (settings); -} - -static void -emae_service_provider_changed (EMAccountEditorService *service) -{ - EConfig *config; - EMConfigTargetSettings *target; - CamelProvider *provider = NULL; - const gchar *description; - - if (service->protocol != NULL) - provider = camel_provider_get (service->protocol, NULL); - - description = (provider != NULL) ? provider->description : ""; - gtk_label_set_text (service->description, description); - - if (provider != NULL) { - gboolean visible_auth; - gboolean visible_host; - gboolean visible_path; - gboolean visible_port; - gboolean visible_user; - gboolean visible_ssl; - gboolean allows; - gboolean hidden; - - emae_setup_settings (service); - - gtk_widget_show (service->frame); - - allows = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_AUTH); - hidden = CAMEL_PROVIDER_HIDDEN (provider, CAMEL_URL_PART_AUTH); - visible_auth = (allows && !hidden); - - allows = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST); - hidden = CAMEL_PROVIDER_HIDDEN (provider, CAMEL_URL_PART_HOST); - visible_host = (allows && !hidden); - - allows = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_PATH); - hidden = CAMEL_PROVIDER_HIDDEN (provider, CAMEL_URL_PART_PATH); - visible_path = (allows && !hidden); - - allows = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_PORT); - hidden = CAMEL_PROVIDER_HIDDEN (provider, CAMEL_URL_PART_PORT); - visible_port = (allows && !hidden); - - allows = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER); - hidden = CAMEL_PROVIDER_HIDDEN (provider, CAMEL_URL_PART_USER); - visible_user = (allows && !hidden); - - switch (service->type) { - case CAMEL_PROVIDER_STORE: - g_object_set ( - service->emae, - "store-visible-auth", visible_auth, - "store-visible-host", visible_host, - "store-visible-path", visible_path, - "store-visible-port", visible_port, - "store-visible-user", visible_user, - NULL); - break; - - case CAMEL_PROVIDER_TRANSPORT: - g_object_set ( - service->emae, - "transport-visible-auth", visible_auth, - "transport-visible-host", visible_host, - "transport-visible-path", visible_path, - "transport-visible-port", visible_port, - "transport-visible-user", visible_user, - NULL); - break; - - default: - g_warn_if_reached (); - } - - if (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_AUTH)) { - if (service->needs_auth && !CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_AUTH)) - gtk_widget_show ((GtkWidget *) service->needs_auth); - } else { - if (service->needs_auth) - gtk_widget_hide ((GtkWidget *) service->needs_auth); - } -#ifdef HAVE_SSL - visible_ssl = - (provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL); - gtk_widget_set_visible (service->ssl_frame, visible_ssl); - gtk_widget_set_visible (service->ssl_hbox, visible_ssl); - gtk_widget_hide (service->no_ssl); -#else - gtk_widget_hide (service->ssl_hbox); - gtk_widget_show (service->no_ssl); -#endif - } else { - gtk_widget_hide (service->frame); - gtk_widget_hide (service->auth_frame); - gtk_widget_hide (service->ssl_frame); - } - - /* Update the EConfigTarget so it has the latest CamelSettings. */ - - config = E_CONFIG (service->emae->priv->config); - target = (EMConfigTargetSettings *) config->target; - - em_config_target_update_settings ( - config, target, - service->emae->priv->modified_account->id->address, - service->emae->priv->source.protocol, - service->emae->priv->source.settings, - service->emae->priv->transport.protocol, - service->emae->priv->transport.settings); -} - -static void -emae_provider_changed (GtkComboBox *combo_box, - EMAccountEditorService *service) -{ - const gchar *active_protocol; - - active_protocol = gtk_combo_box_get_active_id (combo_box); - - if (g_strcmp0 (active_protocol, service->protocol) == 0) - return; - - service->protocol = active_protocol; - - switch (service->type) { - case CAMEL_PROVIDER_STORE: - g_object_notify ( - G_OBJECT (service->emae), - "store-provider"); - break; - case CAMEL_PROVIDER_TRANSPORT: - g_object_notify ( - G_OBJECT (service->emae), - "transport-provider"); - break; - default: - g_warn_if_reached (); - } - - emae_service_provider_changed (service); - - e_config_target_changed ( - (EConfig *) service->emae->priv->config, - E_CONFIG_TARGET_CHANGED_REBUILD); -} - -static void -emae_refresh_providers (EMAccountEditor *emae, - EMAccountEditorService *service) -{ - GtkComboBoxText *combo_box; - GList *link; - - combo_box = GTK_COMBO_BOX_TEXT (service->providers); - - g_signal_handlers_block_by_func ( - combo_box, emae_provider_changed, service); - - gtk_combo_box_text_remove_all (combo_box); - - for (link = emae->priv->providers; link != NULL; link = link->next) { - CamelProvider *provider = link->data; - - /* FIXME This expression is awesomely unreadable! */ - if (!(provider->object_types[service->type] - && (service->type != CAMEL_PROVIDER_STORE || - (provider->flags & CAMEL_PROVIDER_IS_SOURCE) != 0)) - /* hardcode not showing providers who's transport is done in the store */ - || (service->type == CAMEL_PROVIDER_TRANSPORT - && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider))) - continue; - - gtk_combo_box_text_append ( - combo_box, - provider->protocol, - provider->name); - } - - g_signal_handlers_unblock_by_func ( - combo_box, emae_provider_changed, service); - - gtk_combo_box_set_active_id ( - GTK_COMBO_BOX (combo_box), service->protocol); - - /* make sure at least something is selected; - * this applies for cases when user changed from provider which was - * store and transport together, to a store provider only (like from - * exchange to imap provider), which left unselected transport type - */ - if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box)) == -1) - gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0); -} - -static void -emae_authtype_changed (GtkComboBox *combo_box, - EMAccountEditorService *service) -{ - CamelServiceAuthType *authtype = NULL; - const gchar *mechanism; - gboolean sensitive = FALSE; - - mechanism = gtk_combo_box_get_active_id (combo_box); - - if (mechanism != NULL && *mechanism != '\0') { - authtype = camel_sasl_authtype (mechanism); - g_warn_if_fail (authtype != NULL); - } - - sensitive = (authtype == NULL) || (authtype->need_password); - gtk_widget_set_sensitive (GTK_WIDGET (service->remember), sensitive); -} - -static void emae_check_authtype (GtkWidget *w, EMAccountEditorService *service); - -static void -emae_check_authtype_done (CamelService *camel_service, - GAsyncResult *result, - EMAccountEditorService *service) -{ - EMailBackend *backend; - EMailSession *session; - GtkWidget *editor; - GList *available_authtypes; - GError *error = NULL; - - available_authtypes = camel_service_query_auth_types_finish ( - camel_service, result, &error); - - editor = NULL; - if (service->emae && service->emae->config && E_IS_CONFIG (service->emae->config)) - editor = E_CONFIG (service->emae->config)->window; - - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_warn_if_fail (available_authtypes == NULL); - g_error_free (error); - - } else if (error != NULL) { - g_warn_if_fail (available_authtypes == NULL); - if (service->check_dialog) - e_alert_run_dialog_for_args ( - GTK_WINDOW (service->check_dialog), - "mail:checking-service-error", - error->message, NULL); - g_error_free (error); - - } else { - e_auth_combo_box_update_available ( - E_AUTH_COMBO_BOX (service->authtype), - available_authtypes); - g_list_free (available_authtypes); - } - - if (service->check_dialog) { - g_object_weak_unref (G_OBJECT (service->check_dialog), (GWeakNotify) g_nullify_pointer, &service->check_dialog); - gtk_widget_destroy (service->check_dialog); - } - service->check_dialog = NULL; - - if (editor != NULL) - gtk_widget_set_sensitive (editor, TRUE); - - backend = em_account_editor_get_backend (service->emae); - session = e_mail_backend_get_session (backend); - - /* drop the temporary CamelService */ - camel_session_remove_service ( - CAMEL_SESSION (session), camel_service); - - g_object_unref (service->emae); -} - -static void -emae_check_authtype_response (GtkDialog *dialog, - gint button, - GCancellable *cancellable) -{ - g_cancellable_cancel (cancellable); -} - -static void -emae_check_authtype (GtkWidget *w, - EMAccountEditorService *service) -{ - CamelService *camel_service; - EMailBackend *backend; - EMailSession *session; - GtkWidget *editor; - gpointer parent; - gchar *uid; - GError *error = NULL; - - editor = E_CONFIG (service->emae->config)->window; - - backend = em_account_editor_get_backend (service->emae); - session = e_mail_backend_get_session (backend); - - uid = g_strdup_printf ("emae-check-authtype-%p", service); - - /* to test on actual data, not on previously used */ - camel_service = camel_session_add_service ( - CAMEL_SESSION (session), uid, - service->protocol, service->type, &error); - - g_free (uid); - - if (camel_service != NULL && service->settings != NULL) - camel_service_set_settings (camel_service, service->settings); - - if (editor != NULL) - parent = gtk_widget_get_toplevel (editor); - else - parent = gtk_widget_get_toplevel (w); - - if (error) { - e_alert_run_dialog_for_args ( - parent, "mail:checking-service-error", - error->message, NULL); - g_clear_error (&error); - return; - } - - g_return_if_fail (CAMEL_IS_SERVICE (camel_service)); - - if (service->checking != NULL) { - g_cancellable_cancel (service->checking); - g_object_unref (service->checking); - } - - service->checking = g_cancellable_new (); - - service->check_dialog = e_alert_dialog_new_for_args ( - parent, "mail:checking-service", NULL); - g_object_weak_ref (G_OBJECT (service->check_dialog), (GWeakNotify) g_nullify_pointer, &service->check_dialog); - - g_object_ref (service->emae); - - camel_service_query_auth_types ( - camel_service, G_PRIORITY_DEFAULT, - service->checking, (GAsyncReadyCallback) - emae_check_authtype_done, service); - - g_signal_connect ( - service->check_dialog, "response", - G_CALLBACK (emae_check_authtype_response), - service->checking); - - gtk_widget_show (service->check_dialog); - - if (editor != NULL) - gtk_widget_set_sensitive (editor, FALSE); -} - -static void -emae_setup_service (EMAccountEditor *emae, - EMAccountEditorService *service, - GtkBuilder *builder) -{ - struct _service_info *info = &emae_service_info[service->type]; - gboolean requires_auth; - CamelProvider *provider = NULL; - CamelURL *url; - - url = emae_account_url (emae, info->account_uri_key); - - if (!service->protocol) { - /* GtkComboBox internalizes ID strings, which for the provider - * combo box are protocol names. So we'll do the same here. */ - if (url != NULL && url->protocol != NULL) - service->protocol = g_intern_string (url->protocol); - - if (!service->protocol) - service->protocol = "none"; - } - - requires_auth = url && url->authmech != NULL; - - camel_url_free (url); - - if (service->protocol != NULL) - provider = camel_provider_get (service->protocol, NULL); - - /* Extract all widgets we need from the builder file. */ - - service->frame = e_builder_get_widget (builder, info->frame); - service->container = e_builder_get_widget (builder, info->container); - service->description = GTK_LABEL (e_builder_get_widget (builder, info->description)); - service->hostname = GTK_ENTRY (e_builder_get_widget (builder, info->hostname)); - service->hostlabel = (GtkLabel *) e_builder_get_widget (builder, info->hostlabel); - service->port = E_PORT_ENTRY (e_builder_get_widget (builder, info->port)); - service->portlabel = (GtkLabel *) e_builder_get_widget (builder, info->portlabel); - service->username = GTK_ENTRY (e_builder_get_widget (builder, info->username)); - service->userlabel = (GtkLabel *) e_builder_get_widget (builder, info->userlabel); - if (info->pathentry) { - service->pathlabel = (GtkLabel *) e_builder_get_widget (builder, info->pathlabel); - service->pathentry = e_builder_get_widget (builder, info->pathentry); - } - - service->ssl_frame = e_builder_get_widget (builder, info->security_frame); - gtk_widget_hide (service->ssl_frame); - service->ssl_hbox = e_builder_get_widget (builder, info->ssl_hbox); - service->use_ssl = (GtkComboBox *) e_builder_get_widget (builder, info->use_ssl); - service->no_ssl = e_builder_get_widget (builder, info->ssl_disabled); - - service->auth_frame = e_builder_get_widget (builder, info->auth_frame); - service->check_supported = (GtkButton *) e_builder_get_widget (builder, info->authtype_check); - service->authtype = (GtkComboBox *) e_builder_get_widget (builder, info->authtype); - service->providers = (GtkComboBox *) e_builder_get_widget (builder, info->type_dropdown); - - /* XXX GtkComboBoxText, when loaded from a GtkBuilder file, - * needs further manual configuration to be fully usable. - * Particularly the ID column has to be set explicitly. - * https://bugzilla.gnome.org/show_bug.cgi?id=612396#c53 */ - g_object_set ( - service->providers, - "entry-text-column", 0, - "id-column", 1, NULL); - - service->remember = emae_account_toggle (emae, info->remember_password, info->save_passwd_key, builder); - - if (info->needs_auth) { - service->needs_auth = (GtkToggleButton *) e_builder_get_widget (builder, info->needs_auth); - } else { - service->needs_auth = NULL; - } - - g_signal_connect ( - service->providers, "changed", - G_CALLBACK (emae_provider_changed), service); - - if (GTK_IS_FILE_CHOOSER (service->pathentry)) - g_signal_connect ( - service->pathentry, "selection-changed", - G_CALLBACK (emae_file_chooser_changed), service); - - g_signal_connect ( - service->authtype, "changed", - G_CALLBACK (emae_authtype_changed), service); - - g_signal_connect ( - service->check_supported, "clicked", - G_CALLBACK (emae_check_authtype), service); - - switch (service->type) { - case CAMEL_PROVIDER_STORE: - g_object_bind_property ( - emae, "store-provider", - service->authtype, "provider", - G_BINDING_SYNC_CREATE); - - if (service->needs_auth != NULL) { - g_object_set (emae, "store-requires-auth", requires_auth, NULL); - g_object_bind_property ( - emae, "store-requires-auth", - service->needs_auth, "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - g_object_bind_property ( - emae, "store-requires-auth", - service->auth_frame, "sensitive", - G_BINDING_SYNC_CREATE); - } - - g_object_bind_property ( - emae, "store-visible-auth", - service->auth_frame, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-host", - service->hostname, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-host", - service->hostlabel, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-path", - service->pathentry, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-path", - service->pathlabel, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-port", - service->port, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-port", - service->portlabel, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-user", - service->username, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "store-visible-user", - service->userlabel, "visible", - G_BINDING_SYNC_CREATE); - - break; - - case CAMEL_PROVIDER_TRANSPORT: - g_object_bind_property ( - emae, "transport-provider", - service->authtype, "provider", - G_BINDING_SYNC_CREATE); - - if (service->needs_auth != NULL) { - g_object_set (emae, "transport-requires-auth", requires_auth, NULL); - g_object_bind_property ( - emae, "transport-requires-auth", - service->needs_auth, "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - g_object_bind_property ( - emae, "transport-requires-auth", - service->auth_frame, "sensitive", - G_BINDING_SYNC_CREATE); - } - - g_object_bind_property ( - emae, "transport-visible-auth", - service->auth_frame, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "transport-visible-host", - service->hostname, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "transport-visible-host", - service->hostlabel, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "transport-visible-port", - service->port, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "transport-visible-port", - service->portlabel, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "transport-visible-user", - service->username, "visible", - G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - emae, "transport-visible-user", - service->userlabel, "visible", - G_BINDING_SYNC_CREATE); - - break; - - default: - g_warn_if_reached (); - } - - if (service->pathentry) { - GtkFileChooserAction action; - gboolean need_path_dir; - const gchar *label; - - need_path_dir = - (provider == NULL) || - ((provider->url_flags & CAMEL_URL_NEED_PATH_DIR) != 0); - - if (need_path_dir) { - action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - label = _("_Path:"); - } else { - action = GTK_FILE_CHOOSER_ACTION_OPEN; - label = _("Fil_e:"); - } - - if (service->pathlabel) - gtk_label_set_text_with_mnemonic ( - GTK_LABEL (service->pathlabel), label); - - if (action != gtk_file_chooser_get_action (GTK_FILE_CHOOSER (service->pathentry))) - gtk_file_chooser_set_action (GTK_FILE_CHOOSER (service->pathentry), action); - } - - /* old authtype will be destroyed when we exit */ - emae_refresh_providers (emae, service); - - if (provider != NULL && provider->port_entries) { - e_port_entry_set_camel_entries ( - service->port, provider->port_entries); - - /* update also port in settings, because it's not bind yet */ - if (service->settings && CAMEL_IS_NETWORK_SETTINGS (service->settings)) { - camel_network_settings_set_port ( - CAMEL_NETWORK_SETTINGS (service->settings), - e_port_entry_get_port (service->port)); - } - } - - emae_service_provider_changed (service); -} - -static GtkWidget * -emae_create_basic_assistant_page (EMAccountEditor *emae, - GtkAssistant *assistant, - const gchar *page_id, - gint position) -{ - const gchar *title = NULL, *label = NULL; - GtkAssistantPageType page_type = GTK_ASSISTANT_PAGE_CONTENT; - GtkWidget *vbox, *lbl; - gboolean fill_space = FALSE; - - g_return_val_if_fail (page_id != NULL, NULL); - - if (g_ascii_strcasecmp (page_id, "start_page") == 0) { - page_type = GTK_ASSISTANT_PAGE_INTRO; - fill_space = TRUE; - title = _("Mail Configuration"); - label = _("Welcome to the Evolution Mail Configuration Assistant.\n\nClick \"Continue\" to begin."); - } else if (g_ascii_strcasecmp (page_id, "identity_page") == 0) { - title = _("Identity"); - label = _("Please enter your name and email address below. The \"optional\" fields below do not need to be filled in, unless you wish to include this information in email you send."); - } else if (g_ascii_strcasecmp (page_id, "source_page") == 0) { - title = _("Receiving Email"); - label = _("Please configure the following account settings."); - } else if (g_ascii_strcasecmp (page_id, "transport_page") == 0) { - title = _("Sending Email"); - label = _("Please enter information about the way you will send mail. If you are not sure, ask your system administrator or Internet Service Provider."); - } else if (g_ascii_strcasecmp (page_id, "review_page") == 0) { - title = _("Account Summary"); - label = _("This is a summary of the settings which will be used to access your mail."); - } else if (g_ascii_strcasecmp (page_id, "finish_page") == 0) { - page_type = GTK_ASSISTANT_PAGE_CONFIRM; - fill_space = TRUE; - title = _("Done"); - label = _("Congratulations, your mail configuration is complete.\n\nYou are now ready to send and receive email using Evolution.\n\nClick \"Apply\" to save your settings."); - } else { - g_return_val_if_reached (NULL); - } - - vbox = gtk_vbox_new (FALSE, 12); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); - gtk_widget_show (vbox); - - lbl = gtk_label_new (label); - gtk_label_set_line_wrap (GTK_LABEL (lbl), TRUE); - gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox), lbl, fill_space, fill_space, 0); - gtk_widget_show (lbl); - - if (g_ascii_strcasecmp (page_id, "start_page") == 0) - g_hash_table_insert (emae->priv->widgets, (gchar *)"start_page_label", lbl); - - gtk_assistant_insert_page (assistant, vbox, position); - gtk_assistant_set_page_title (assistant, vbox, title); - gtk_assistant_set_page_type (assistant, vbox, page_type); - - return vbox; -} - -/* do not re-order these, the order is used by various code to look up emae->priv->identity_entries[] */ -static struct { - const gchar *name; - gint item; -} emae_identity_entries[] = { - { "management_name", E_ACCOUNT_NAME }, - { "identity_full_name", E_ACCOUNT_ID_NAME }, - { "identity_address", E_ACCOUNT_ID_ADDRESS }, - { "identity_reply_to", E_ACCOUNT_ID_REPLY_TO }, - { "identity_organization", E_ACCOUNT_ID_ORGANIZATION }, -}; - -static void -emae_queue_widgets (EMAccountEditor *emae, - GtkBuilder *builder, - const gchar *first, - ...) -{ - va_list ap; - - va_start (ap, first); - while (first) { - g_hash_table_insert (emae->priv->widgets, (gchar *) first, e_builder_get_widget (builder, first)); - first = va_arg (ap, const gchar *); - } - va_end (ap); -} - -static GtkWidget * -emae_identity_page (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *priv = emae->priv; - EAccount *account; - gint i; - GtkWidget *w; - GtkBuilder *builder; - - if (old && emae->type == EMAE_PAGES) - return old; - - account = em_account_editor_get_modified_account (emae); - - /* Make sure our custom widget classes are registered with - * GType before we load the GtkBuilder definition file. */ - E_TYPE_MAIL_JUNK_OPTIONS; - EM_TYPE_FOLDER_SELECTION_BUTTON; - - builder = gtk_builder_new (); - e_load_ui_builder_definition (builder, "mail-config.ui"); - - /* Management & Identity fields, in the assistant the management frame is relocated to the last page later on */ - for (i = 0; i < G_N_ELEMENTS (emae_identity_entries); i++) - priv->identity_entries[i] = emae_account_entry (emae, emae_identity_entries[i].name, emae_identity_entries[i].item, builder); - - priv->management_frame = e_builder_get_widget (builder, "management-section"); - - priv->default_account = GTK_TOGGLE_BUTTON (e_builder_get_widget (builder, "management_default")); - if (!e_get_default_account () - || (account == e_get_default_account ()) - || (GPOINTER_TO_INT(g_object_get_data (G_OBJECT (account), "default_flagged"))) ) - gtk_toggle_button_set_active (priv->default_account, TRUE); - - if (emae->do_signature) { - emae_setup_signatures (emae, builder); - } else { - /* TODO: this could/should probably be neater */ - gtk_widget_hide (e_builder_get_widget (builder, "sigLabel")); -#if 0 - gtk_widget_hide (e_builder_get_widget (builder, "sigOption")); -#endif - gtk_widget_hide (e_builder_get_widget (builder, "signature_dropdown")); - gtk_widget_hide (e_builder_get_widget (builder, "sigAddNew")); - } - - w = e_builder_get_widget (builder, item->label); - if (emae->type == EMAE_PAGES) { - GtkWidget *page = emae_create_basic_assistant_page (emae, GTK_ASSISTANT (parent), "identity_page", position); - - gtk_box_pack_start ((GtkBox *) emae->pages[0], w, TRUE, TRUE, 0); - w = page; - } else if (((EConfig *) priv->config)->type == E_CONFIG_ASSISTANT) { - GtkWidget *page; - - page = emae_create_basic_assistant_page ( - emae, GTK_ASSISTANT (parent), - "identity_page", position); - - gtk_box_pack_start (GTK_BOX (page), w, TRUE, TRUE, 0); - - w = page; - } else { - gtk_notebook_insert_page ( - GTK_NOTEBOOK (parent), w, - gtk_label_new (_("Identity")), - position); - gtk_container_child_set ( - GTK_CONTAINER (parent), w, - "tab-fill", FALSE, "tab-expand", FALSE, NULL); - } - - emae_queue_widgets ( - emae, builder, - "account_vbox", - "identity-required-table", - "identity-optional-table", - "identity-optional-section", - "identity_address", - NULL); - - g_object_unref (builder); - - return w; -} - -static GtkWidget * -emae_receive_page (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *priv = emae->priv; - GtkWidget *w; - GtkBuilder *builder; - - /*if (old) - return old;*/ - - builder = gtk_builder_new (); - e_load_ui_builder_definition (builder, "mail-config.ui"); - - priv->source.type = CAMEL_PROVIDER_STORE; - emae_setup_service (emae, &priv->source, builder); - - w = e_builder_get_widget (builder, item->label); - if (emae->type == EMAE_PAGES) { - GtkWidget *page = emae_create_basic_assistant_page (emae, GTK_ASSISTANT (parent), "source_page", position); - GtkWidget *vbox, *child; - - child = (GtkWidget *)g_object_get_data ((GObject *)emae->pages[1], "old-child"); - if (child) - gtk_container_remove ((GtkContainer *) emae->pages[1], child); - - vbox = gtk_vbox_new (FALSE, 12); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); - gtk_widget_show (vbox); - gtk_box_pack_start ((GtkBox *) vbox, w, TRUE, TRUE, 0); - g_object_set_data ((GObject *)emae->pages[1], "old-child", vbox); - gtk_box_pack_start ((GtkBox *) emae->pages[1], vbox, TRUE, TRUE, 0); - - w = page; - } else if (((EConfig *) priv->config)->type == E_CONFIG_ASSISTANT) { - GtkWidget *page; - - page = emae_create_basic_assistant_page ( - emae, GTK_ASSISTANT (parent), - "source_page", position); - - gtk_box_pack_start (GTK_BOX (page), w, TRUE, TRUE, 0); - - w = page; - } else { - gtk_notebook_insert_page ( - GTK_NOTEBOOK (parent), w, - gtk_label_new (_("Receiving Email")), - position); - gtk_container_child_set ( - GTK_CONTAINER (parent), w, - "tab-fill", FALSE, "tab-expand", FALSE, NULL); - } - - emae_queue_widgets ( - emae, builder, - "source-type-table", - "source-config-table", - "source-security-vbox", - "source-auth-vbox", - NULL); - - g_object_unref (builder); - - return w; -} - -static void -emae_set_option_dependency (EMAccountEditorService *service, - CamelProviderConfEntry *conf, - GtkWidget *widget) -{ - if (conf->depname != NULL) { - const gchar *depname = conf->depname; - - if (*depname == '!') - depname++; - - g_object_bind_property ( - service->settings, depname, - widget, "sensitive", - G_BINDING_SYNC_CREATE | - (depname == conf->depname ? 0 : G_BINDING_INVERT_BOOLEAN)); - gtk_widget_set_margin_left (widget, INDENT_MARGIN); - } -} - -static GtkWidget * -emae_option_toggle (EMAccountEditorService *service, - CamelProviderConfEntry *conf) -{ - GtkWidget *widget; - - widget = gtk_check_button_new_with_mnemonic (conf->text); - - g_object_bind_property ( - service->settings, conf->name, - widget, "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - emae_set_option_dependency (service, conf, widget); - - return widget; -} - -static GtkWidget * -emae_option_entry (EMAccountEditorService *service, - CamelProviderConfEntry *conf, - GtkLabel *label_for_mnemonic) -{ - GtkWidget *widget; - - widget = gtk_entry_new (); - gtk_label_set_mnemonic_widget (label_for_mnemonic, widget); - - g_object_bind_property ( - service->settings, conf->name, - widget, "text", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - emae_set_option_dependency (service, conf, widget); - - g_object_bind_property ( - widget, "sensitive", - label_for_mnemonic, "sensitive", - G_BINDING_SYNC_CREATE); - - return widget; -} - -static GtkWidget * -emae_option_checkspin (EMAccountEditorService *service, - CamelProviderConfEntry *conf) -{ - GObjectClass *class; - GParamSpec *pspec; - GParamSpec *use_pspec; - GtkAdjustment *adjustment; - GtkWidget *hbox, *spin; - GtkWidget *prefix; - gchar *use_property_name; - gchar *pre, *post; - - /* The conf->name property (e.g. "foo") should be numeric for the - * spin button. If a "use" boolean property exists (e.g. "use-foo") - * then a checkbox is also shown. */ - - g_return_val_if_fail (conf->name != NULL, NULL); - - class = G_OBJECT_GET_CLASS (service->settings); - pspec = g_object_class_find_property (class, conf->name); - g_return_val_if_fail (pspec != NULL, NULL); - - use_property_name = g_strconcat ("use-", conf->name, NULL); - use_pspec = g_object_class_find_property (class, use_property_name); - if (use_pspec != NULL && use_pspec->value_type != G_TYPE_BOOLEAN) - use_pspec = NULL; - g_free (use_property_name); - - /* Make sure we can convert to and from doubles. */ - g_return_val_if_fail ( - g_value_type_transformable ( - pspec->value_type, G_TYPE_DOUBLE), NULL); - g_return_val_if_fail ( - g_value_type_transformable ( - G_TYPE_DOUBLE, pspec->value_type), NULL); - - if (G_IS_PARAM_SPEC_CHAR (pspec)) { - GParamSpecChar *pspec_char; - pspec_char = G_PARAM_SPEC_CHAR (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_char->default_value, - (gdouble) pspec_char->minimum, - (gdouble) pspec_char->maximum, - 1.0, 1.0, 0.0); - - } else if (G_IS_PARAM_SPEC_UCHAR (pspec)) { - GParamSpecUChar *pspec_uchar; - pspec_uchar = G_PARAM_SPEC_UCHAR (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_uchar->default_value, - (gdouble) pspec_uchar->minimum, - (gdouble) pspec_uchar->maximum, - 1.0, 1.0, 0.0); - - } else if (G_IS_PARAM_SPEC_INT (pspec)) { - GParamSpecInt *pspec_int; - pspec_int = G_PARAM_SPEC_INT (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_int->default_value, - (gdouble) pspec_int->minimum, - (gdouble) pspec_int->maximum, - 1.0, 1.0, 0.0); - - } else if (G_IS_PARAM_SPEC_UINT (pspec)) { - GParamSpecUInt *pspec_uint; - pspec_uint = G_PARAM_SPEC_UINT (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_uint->default_value, - (gdouble) pspec_uint->minimum, - (gdouble) pspec_uint->maximum, - 1.0, 1.0, 0.0); - - } else if (G_IS_PARAM_SPEC_LONG (pspec)) { - GParamSpecLong *pspec_long; - pspec_long = G_PARAM_SPEC_LONG (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_long->default_value, - (gdouble) pspec_long->minimum, - (gdouble) pspec_long->maximum, - 1.0, 1.0, 0.0); - - } else if (G_IS_PARAM_SPEC_ULONG (pspec)) { - GParamSpecULong *pspec_ulong; - pspec_ulong = G_PARAM_SPEC_ULONG (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_ulong->default_value, - (gdouble) pspec_ulong->minimum, - (gdouble) pspec_ulong->maximum, - 1.0, 1.0, 0.0); - - } else if (G_IS_PARAM_SPEC_FLOAT (pspec)) { - GParamSpecFloat *pspec_float; - pspec_float = G_PARAM_SPEC_FLOAT (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_float->default_value, - (gdouble) pspec_float->minimum, - (gdouble) pspec_float->maximum, - 1.0, 1.0, 0.0); - - } else if (G_IS_PARAM_SPEC_DOUBLE (pspec)) { - GParamSpecDouble *pspec_double; - pspec_double = G_PARAM_SPEC_DOUBLE (pspec); - adjustment = gtk_adjustment_new ( - (gdouble) pspec_double->default_value, - (gdouble) pspec_double->minimum, - (gdouble) pspec_double->maximum, - 1.0, 1.0, 0.0); - - } else - g_return_val_if_reached (NULL); - - pre = g_alloca (strlen (conf->text) + 1); - strcpy (pre, conf->text); - post = strstr (pre, "%s"); - if (post != NULL) { - *post = '\0'; - post += 2; - } - - hbox = gtk_hbox_new (FALSE, 3); - - if (use_pspec != NULL) { - prefix = gtk_check_button_new_with_mnemonic (pre); - - g_object_bind_property ( - service->settings, use_pspec->name, - prefix, "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - } else { - prefix = gtk_label_new_with_mnemonic (pre); - } - gtk_box_pack_start (GTK_BOX (hbox), prefix, FALSE, TRUE, 0); - gtk_widget_show (prefix); - - spin = gtk_spin_button_new (adjustment, 1.0, 0); - gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, TRUE, 0); - gtk_widget_show (spin); - - g_object_bind_property ( - service->settings, conf->name, - spin, "value", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - if (use_pspec != NULL) - g_object_bind_property ( - prefix, "active", - spin, "sensitive", - G_BINDING_SYNC_CREATE); - - if (post != NULL) { - GtkWidget *label = gtk_label_new_with_mnemonic (post); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), prefix); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); - gtk_widget_show (label); - } - - emae_set_option_dependency (service, conf, hbox); - - return hbox; -} - -/* 'values' is in format "nick0:caption0:nick1:caption1:...nickN:captionN" - * where 'nick' is the nickname of a GEnumValue belonging to a GEnumClass - * determined by the type of the GObject property named "name". */ -static GtkWidget * -emae_option_options (EMAccountEditorService *service, - CamelProviderConfEntry *conf, - GtkLabel *label) -{ - CamelProvider *provider; - GtkWidget *widget; - GtkListStore *store; - GtkTreeIter iter; - const gchar *p; - GtkCellRenderer *renderer; - - provider = camel_provider_get (service->protocol, NULL); - g_return_val_if_fail (provider != NULL, NULL); - - /* nick and caption */ - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - - p = conf->value; - while (p != NULL) { - const gchar *nick; - const gchar *caption; - gchar *vl, *cp; - - nick = p; - caption = strchr (p, ':'); - if (caption) { - caption++; - } else { - g_warning (G_STRLOC ": expected ':' not found at '%s'", p); - break; - } - p = strchr (caption, ':'); - - vl = g_strndup (nick, caption - nick - 1); - if (p) { - p++; - cp = g_strndup (caption, p - caption - 1); - } else - cp = g_strdup (caption); - - gtk_list_store_append (store, &iter); - gtk_list_store_set ( - store, &iter, 0, vl, 1, dgettext ( - provider->translation_domain, cp), -1); - - g_free (vl); - g_free (cp); - } - - widget = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)); - gtk_combo_box_set_id_column (GTK_COMBO_BOX (widget), 0); - gtk_widget_show (widget); - - g_object_bind_property_full ( - service->settings, conf->name, - widget, "active-id", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE, - e_binding_transform_enum_value_to_nick, - e_binding_transform_enum_nick_to_value, - NULL, (GDestroyNotify) NULL); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), renderer, TRUE); - gtk_cell_layout_set_attributes ( - GTK_CELL_LAYOUT (widget), renderer, "text", 1, NULL); - - gtk_label_set_mnemonic_widget (label, widget); - - return widget; -} - -static GtkWidget * -emae_receive_options_item (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; - CamelProvider *provider; - GtkWidget *w, *box, *spin; - guint row; - - provider = emae_get_store_provider (emae); - - if (provider == NULL || provider->extra_conf == NULL) - return NULL; - - if (old) { - if (emae->type == EMAE_PAGES) { - GtkWidget *box = gtk_hbox_new (FALSE, 12); - gtk_widget_reparent (old, box); - gtk_widget_show (box); - gtk_box_set_child_packing ((GtkBox *) box, old, TRUE, TRUE, 12, GTK_PACK_START); - gtk_box_pack_end ((GtkBox *) emae->pages[2], box, FALSE, FALSE, 0); - } - return old; - } - - if (emae->type == EMAE_PAGES) { - GtkWidget *box = gtk_hbox_new (FALSE, 12); - gtk_widget_reparent (parent, box); - gtk_widget_show (box); - gtk_box_set_child_packing ((GtkBox *) box, parent, TRUE, TRUE, 12, GTK_PACK_START); - gtk_box_pack_start ((GtkBox *) emae->pages[2], box, FALSE, FALSE, 0); - } - - /* We have to add the automatic mail check item with the rest of the receive options */ - g_object_get (parent, "n-rows", &row, NULL); - - box = gtk_hbox_new (FALSE, 4); - w = gtk_check_button_new_with_mnemonic (_("Check for _new messages every")); - emae_account_toggle_widget (emae, (GtkToggleButton *) w, E_ACCOUNT_SOURCE_AUTO_CHECK); - gtk_box_pack_start ((GtkBox *) box, w, FALSE, FALSE, 0); - - spin = gtk_spin_button_new_with_range (1.0, 1440.0, 1.0); - emae_account_spinint_widget (emae, (GtkSpinButton *) spin, E_ACCOUNT_SOURCE_AUTO_CHECK_TIME); - gtk_box_pack_start ((GtkBox *) box, spin, FALSE, TRUE, 0); - - w = gtk_label_new_with_mnemonic (_("minu_tes")); - gtk_label_set_mnemonic_widget (GTK_LABEL (w), spin); - gtk_box_pack_start ((GtkBox *) box, w, FALSE, FALSE, 0); - - gtk_widget_show_all (box); - - gtk_table_attach ((GtkTable *) parent, box, 0, 2, row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - - return box; -} - -static GtkWidget * -emae_receive_options_extra_item (EConfig *ec, - EConfigItem *eitem, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorService *service; - struct _receive_options_item *item = (struct _receive_options_item *) eitem; - GtkWidget *box; - GtkWidget *widget; - GtkLabel *label; - GtkTable *table; - CamelProvider *provider; - CamelProviderConfEntry *entries; - guint row; - GHashTable *extra; - const gchar *section_name; - gint ii; - - service = &emae->priv->source; - section_name = eitem->user_data; - - provider = emae_get_store_provider (emae); - - if (provider == NULL || provider->extra_conf == NULL) - return NULL; - - entries = provider->extra_conf; - - if (emae->type == EMAE_PAGES) { - GtkWidget *box; - - box = gtk_hbox_new (FALSE, 12); - gtk_widget_reparent (parent, box); - gtk_widget_show (box); - gtk_box_set_child_packing ( - GTK_BOX (box), parent, - TRUE, TRUE, 12, GTK_PACK_START); - gtk_box_pack_start ( - GTK_BOX (emae->pages[2]), box, FALSE, FALSE, 0); - } - - for (ii = 0; entries && entries[ii].type != CAMEL_PROVIDER_CONF_END; ii++) - if (entries[ii].type == CAMEL_PROVIDER_CONF_SECTION_START - && g_strcmp0 (entries[ii].name, section_name) == 0) - goto section; - - return NULL; - -section: - d (printf ("Building extra section '%s'\n", eitem->path)); - widget = NULL; - item->extra_table = g_hash_table_new (g_str_hash, g_str_equal); - extra = g_hash_table_new (g_str_hash, g_str_equal); - - table = GTK_TABLE (parent); - g_object_get (table, "n-rows", &row, NULL); - - for (; entries[ii].type != CAMEL_PROVIDER_CONF_END && entries[ii].type != CAMEL_PROVIDER_CONF_SECTION_END; ii++) { - switch (entries[ii].type) { - case CAMEL_PROVIDER_CONF_SECTION_START: - case CAMEL_PROVIDER_CONF_SECTION_END: - break; - - case CAMEL_PROVIDER_CONF_LABEL: - /* FIXME This is a hack for exchange connector, - * labels should be removed from confentry. */ - if (!strcmp (entries[ii].name, "hostname")) - label = emae->priv->source.hostlabel; - else if (!strcmp (entries[ii].name, "username")) - label = emae->priv->source.userlabel; - else - label = NULL; - - if (label != NULL) - gtk_label_set_text_with_mnemonic ( - label, entries[ii].text); - break; - - case CAMEL_PROVIDER_CONF_CHECKBOX: - widget = emae_option_toggle (service, &entries[ii]); - gtk_table_attach ( - table, widget, 0, 2, - row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - gtk_widget_show (widget); - - g_hash_table_insert ( - extra, (gpointer) entries[ii].name, widget); - - row++; - - /* HACK: keep_on_server is stored in the e-account, - * but is displayed as a properly on the uri, make - * sure they track/match here. */ - if (strcmp (entries[ii].name, "keep-on-server") == 0) - emae_account_toggle_widget ( - emae, (GtkToggleButton *) widget, - E_ACCOUNT_SOURCE_KEEP_ON_SERVER); - break; - - case CAMEL_PROVIDER_CONF_ENTRY: - widget = gtk_label_new_with_mnemonic (entries[ii].text); - gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); - gtk_table_attach ( - table, widget, 0, 1, - row, row + 1, GTK_FILL, 0, 0, 0); - gtk_widget_show (widget); - - label = GTK_LABEL (widget); - - widget = emae_option_entry ( - service, &entries[ii], label); - gtk_table_attach ( - table, widget, 1, 2, - row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - gtk_widget_show (widget); - - row++; - - /* FIXME This is another hack for - * exchange/groupwise connector. */ - g_hash_table_insert ( - item->extra_table, - (gpointer) entries[ii].name, widget); - break; - - case CAMEL_PROVIDER_CONF_CHECKSPIN: - widget = emae_option_checkspin (service, &entries[ii]); - gtk_table_attach ( - table, widget, 0, 2, - row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - gtk_widget_show (widget); - row++; - break; - - case CAMEL_PROVIDER_CONF_OPTIONS: - box = gtk_hbox_new (FALSE, 4); - gtk_table_attach ( - table, box, 0, 2, - row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - gtk_widget_show (box); - - widget = gtk_label_new_with_mnemonic (entries[ii].text); - gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); - gtk_box_pack_start ( - GTK_BOX (box), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - label = GTK_LABEL (widget); - - widget = emae_option_options ( - service, &entries[ii], label); - gtk_box_pack_start ( - GTK_BOX (box), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - row++; - break; - - default: - break; - } - } - - if (widget != NULL) - gtk_widget_show (widget); - - return widget; -} - -static GtkWidget * -emae_send_page (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *priv = emae->priv; - CamelProvider *provider; - GtkWidget *w; - GtkBuilder *builder; - - provider = emae_get_store_provider (emae); - - /* no transport options page at all for these types of providers */ - if (provider && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) { - memset (&priv->transport.frame, 0, ((gchar *) &priv->transport.check_dialog) - ((gchar *) &priv->transport.frame)); - priv->transport.protocol = provider->protocol; - return NULL; - } - - builder = gtk_builder_new (); - e_load_ui_builder_definition (builder, "mail-config.ui"); - - /* Transport */ - priv->transport.type = CAMEL_PROVIDER_TRANSPORT; - emae_setup_service (emae, &priv->transport, builder); - - w = e_builder_get_widget (builder, item->label); - if (emae->type == EMAE_PAGES) { - GtkWidget *page = emae_create_basic_assistant_page (emae, GTK_ASSISTANT (parent), "transport_page", position); - GtkWidget *vbox, *child; - - child = (GtkWidget *)g_object_get_data ((GObject *)emae->pages[3], "old-child"); - if (child) - gtk_container_remove ((GtkContainer *) emae->pages[3], child); - - vbox = gtk_vbox_new (FALSE, 12); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); - gtk_widget_show (vbox); - gtk_box_pack_start ((GtkBox *) vbox, w, TRUE, TRUE, 0); - g_object_set_data ((GObject *)emae->pages[3], "old-child", vbox); - - gtk_box_pack_start ((GtkBox *) emae->pages[3], vbox, TRUE, TRUE, 0); - - w = page; - } else if (((EConfig *) priv->config)->type == E_CONFIG_ASSISTANT) { - GtkWidget *page; - - page = emae_create_basic_assistant_page ( - emae, GTK_ASSISTANT (parent), - "transport_page", position); - - gtk_box_pack_start (GTK_BOX (page), w, TRUE, TRUE, 0); - - w = page; - } else { - gtk_notebook_insert_page ( - GTK_NOTEBOOK (parent), w, - gtk_label_new (_("Sending Email")), - position); - gtk_container_child_set ( - GTK_CONTAINER (parent), w, - "tab-fill", FALSE, "tab-expand", FALSE, NULL); - } - - emae_queue_widgets ( - emae, builder, - "transport-type-table", - "transport-server-table", - "transport-security-table", - "transport-auth-table", - NULL); - - g_object_unref (builder); - - return w; -} - -static void -emae_real_url_toggled (GtkToggleButton *check, - EMFolderSelectionButton *button) -{ - if (!gtk_toggle_button_get_active (check)) - em_folder_selection_button_set_folder_uri (button, ""); -} - -static void -set_real_folder_path (GtkButton *folder_button, - CamelSettings *settings, - const gchar *settings_prop, - EAccount *account) -{ - gchar *path = NULL, *uri; - gchar *encoded_name; - gchar *encoded_uid; - const gchar *folder_name; - - g_return_if_fail (folder_button != NULL); - g_return_if_fail (settings != NULL); - g_return_if_fail (settings_prop != NULL); - g_return_if_fail (account != NULL); - - g_object_get (G_OBJECT (settings), settings_prop, &path, NULL); - - if (!path || !*path) { - g_free (path); - return; - } - - folder_name = path; - - /* Skip the leading slash, if present. */ - if (*folder_name == '/') - folder_name++; - - encoded_uid = camel_url_encode (account->uid, ":;@/"); - encoded_name = camel_url_encode (folder_name, "#"); - - uri = g_strdup_printf ("folder://%s/%s", encoded_uid, encoded_name); - - g_free (encoded_uid); - g_free (encoded_name); - g_free (path); - - em_folder_selection_button_set_folder_uri (EM_FOLDER_SELECTION_BUTTON (folder_button), uri); - - g_free (uri); -} - -static void -update_real_folder_cb (GtkButton *folder_button, - GParamSpec *par_spec, - EMAccountEditor *emae) -{ - EMFolderSelectionButton *sel_button; - CamelSettings *settings; - const gchar *prop_name = NULL; - const gchar *folder_uri; - gchar *path = NULL; - - g_return_if_fail (folder_button != NULL); - g_return_if_fail (emae != NULL); - g_return_if_fail (emae->priv != NULL); - - settings = emae->priv->source.settings; - if (folder_button == emae->priv->trash_folder_button) - prop_name = "real-trash-path"; - else if (folder_button == emae->priv->junk_folder_button) - prop_name = "real-junk-path"; - - g_return_if_fail (prop_name != NULL); - - sel_button = EM_FOLDER_SELECTION_BUTTON (folder_button); - g_return_if_fail (sel_button != NULL); - - folder_uri = em_folder_selection_button_get_folder_uri (sel_button); - if (folder_uri && *folder_uri) { - EMailSession *session; - - session = em_folder_selection_button_get_session (sel_button); - if (!e_mail_folder_uri_parse (CAMEL_SESSION (session), folder_uri, NULL, &path, NULL)) - path = NULL; - } - - g_object_set (G_OBJECT (settings), prop_name, path, NULL); - g_free (path); -} - -static GtkWidget * -emae_defaults_page (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *priv = emae->priv; - EMFolderSelectionButton *button; - CamelProviderFlags flags; - CamelProvider *provider; - CamelSettings *settings; - CamelStore *store = NULL; - EMailBackend *backend; - EMailSession *session; - EAccount *account; - GtkWidget *widget; - GtkBuilder *builder; - GParamSpec *pspec; - gboolean visible; - - /*if (old) - return old;*/ - if (((EConfig *) priv->config)->type == E_CONFIG_ASSISTANT && emae->type != EMAE_PAGES) - return NULL; - - account = em_account_editor_get_modified_account (emae); - backend = em_account_editor_get_backend (emae); - - session = e_mail_backend_get_session (backend); - - if (account != NULL) { - CamelService *service; - - service = camel_session_get_service ( - CAMEL_SESSION (session), account->uid); - - if (CAMEL_IS_STORE (service)) - store = CAMEL_STORE (service); - } - - provider = emae_get_store_provider (emae); - settings = emae->priv->source.settings; - - /* Make sure we have a valid EMailBackend. */ - g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); - - builder = gtk_builder_new (); - e_load_ui_builder_definition (builder, "mail-config.ui"); - - /* Special folders */ - button = emae_account_folder ( - emae, "drafts_button", - E_ACCOUNT_DRAFTS_FOLDER_URI, - E_MAIL_LOCAL_FOLDER_DRAFTS, builder); - priv->drafts_folder_button = GTK_BUTTON (button); - - button = emae_account_folder ( - emae, "sent_button", - E_ACCOUNT_SENT_FOLDER_URI, - E_MAIL_LOCAL_FOLDER_SENT, builder); - priv->sent_folder_button = GTK_BUTTON (button); - - widget = e_builder_get_widget (builder, "trash_folder_check"); - priv->trash_folder_check = GTK_TOGGLE_BUTTON (widget); - - widget = e_builder_get_widget (builder, "trash_folder_butt"); - button = EM_FOLDER_SELECTION_BUTTON (widget); - em_folder_selection_button_set_session (button, session); - em_folder_selection_button_set_store (button, store); - priv->trash_folder_button = GTK_BUTTON (button); - - g_signal_connect ( - priv->trash_folder_check, "toggled", - G_CALLBACK (emae_real_url_toggled), - priv->trash_folder_button); - - g_object_bind_property ( - priv->trash_folder_check, "active", - priv->trash_folder_button, "sensitive", - G_BINDING_SYNC_CREATE); - - if (settings != NULL) - pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (settings), - "use-real-trash-path"); - else - pspec = NULL; - - if (pspec != NULL) - g_object_bind_property ( - settings, "use-real-trash-path", - priv->trash_folder_check, "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - if (settings != NULL) - pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (settings), - "real-trash-path"); - else - pspec = NULL; - - if (pspec != NULL) { - set_real_folder_path ( - priv->trash_folder_button, - settings, "real-trash-path", account); - g_signal_connect ( - priv->trash_folder_button, "notify::folder-uri", - G_CALLBACK (update_real_folder_cb), emae); - } - - flags = CAMEL_PROVIDER_ALLOW_REAL_TRASH_FOLDER; - visible = - (provider != NULL) && - ((provider->flags & flags) != 0); - widget = GTK_WIDGET (priv->trash_folder_check); - gtk_widget_set_visible (widget, visible); - widget = GTK_WIDGET (priv->trash_folder_button); - gtk_widget_set_visible (widget, visible); - - widget = e_builder_get_widget (builder, "junk_folder_check"); - priv->junk_folder_check = GTK_TOGGLE_BUTTON (widget); - - widget = e_builder_get_widget (builder, "junk_folder_butt"); - button = EM_FOLDER_SELECTION_BUTTON (widget); - em_folder_selection_button_set_session (button, session); - em_folder_selection_button_set_store (button, store); - priv->junk_folder_button = GTK_BUTTON (button); - - g_signal_connect ( - priv->junk_folder_check, "toggled", - G_CALLBACK (emae_real_url_toggled), - priv->junk_folder_button); - - g_object_bind_property ( - priv->junk_folder_check, "active", - priv->junk_folder_button, "sensitive", - G_BINDING_SYNC_CREATE); - - if (settings != NULL) - pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (settings), - "use-real-junk-path"); - else - pspec = NULL; - - if (pspec != NULL) - g_object_bind_property ( - settings, "use-real-junk-path", - priv->junk_folder_check, "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - if (settings != NULL) - pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (settings), - "real-junk-path"); - else - pspec = NULL; - - if (pspec != NULL) { - set_real_folder_path ( - priv->junk_folder_button, - settings, "real-junk-path", account); - g_signal_connect ( - priv->junk_folder_button, "notify::folder-uri", - G_CALLBACK (update_real_folder_cb), emae); - } - - flags = CAMEL_PROVIDER_ALLOW_REAL_JUNK_FOLDER; - visible = - (provider != NULL) && - ((provider->flags & flags) != 0); - widget = GTK_WIDGET (priv->junk_folder_check); - gtk_widget_set_visible (widget, visible); - widget = GTK_WIDGET (priv->junk_folder_button); - gtk_widget_set_visible (widget, visible); - - /* Special Folders "Reset Defaults" button */ - priv->restore_folders_button = (GtkButton *)e_builder_get_widget (builder, "default_folders_button"); - g_signal_connect ( - priv->restore_folders_button, "clicked", - G_CALLBACK (default_folders_clicked), emae); - - /* Always Cc/Bcc */ - emae_account_toggle (emae, "always_cc", E_ACCOUNT_CC_ALWAYS, builder); - emae_account_entry (emae, "cc_addrs", E_ACCOUNT_CC_ADDRS, builder); - emae_account_toggle (emae, "always_bcc", E_ACCOUNT_BCC_ALWAYS, builder); - emae_account_entry (emae, "bcc_addrs", E_ACCOUNT_BCC_ADDRS, builder); - - gtk_widget_set_sensitive ( - GTK_WIDGET (priv->sent_folder_button), - (provider ? !(provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER) : TRUE)); - - gtk_widget_set_sensitive ( - GTK_WIDGET (priv->restore_folders_button), - (provider && !(provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER))); - - /* Receipt policy */ - emae_setup_receipt_policy (emae, builder); - - widget = e_builder_get_widget (builder, item->label); - if (emae->type == EMAE_PAGES) { - gtk_box_pack_start ((GtkBox *) emae->pages[4], widget, TRUE, TRUE, 0); - gtk_widget_show (widget); - } else { - gtk_notebook_insert_page ( - GTK_NOTEBOOK (parent), widget, - gtk_label_new (_("Defaults")), - position); - gtk_container_child_set ( - GTK_CONTAINER (parent), widget, - "tab-fill", FALSE, "tab-expand", FALSE, NULL); - } - - emae_queue_widgets ( - emae, builder, - "special-folders-table", - "composing-messages-table", - NULL); - - g_object_unref (builder); - - return widget; -} - -static void -emae_account_hash_algo_combo_changed_cb (GtkComboBox *combobox, - EMAccountEditor *emae) -{ - EAccount *account; - gpointer data; - const gchar *text = NULL; - - account = em_account_editor_get_modified_account (emae); - data = g_object_get_data (G_OBJECT (combobox), "account-item"); - - switch (gtk_combo_box_get_active (combobox)) { - case 1: text = "sha1"; - break; - case 2: text = "sha256"; - break; - case 3: - text = "sha384"; - break; - case 4: - text = "sha512"; - break; - } - - e_account_set_string (account, GPOINTER_TO_INT (data), text); -} - -static GtkComboBox * -emae_account_hash_algo_combo (EMAccountEditor *emae, - const gchar *name, - gint item, - GtkBuilder *builder) -{ - EAccount *account; - GtkComboBox *combobox; - const gchar *text; - gint index = 0; - - account = em_account_editor_get_modified_account (emae); - combobox = GTK_COMBO_BOX (e_builder_get_widget (builder, name)); - g_return_val_if_fail (combobox != NULL, NULL); - - text = e_account_get_string (account, item); - if (text) { - if (g_ascii_strcasecmp (text, "sha1") == 0) - index = 1; - else if (g_ascii_strcasecmp (text, "sha256") == 0) - index = 2; - else if (g_ascii_strcasecmp (text, "sha384") == 0) - index = 3; - else if (g_ascii_strcasecmp (text, "sha512") == 0) - index = 4; - } - - gtk_combo_box_set_active (combobox, index); - - g_object_set_data (G_OBJECT (combobox), "account-item", GINT_TO_POINTER (item)); - g_signal_connect ( - combobox, "changed", - G_CALLBACK (emae_account_hash_algo_combo_changed_cb), emae); - - return combobox; -} - -static GtkWidget * -emae_security_page (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; -#if defined (HAVE_NSS) && defined (ENABLE_SMIME) - EMAccountEditorPrivate *priv = emae->priv; -#endif - GtkWidget *w; - GtkBuilder *builder; - - /*if (old) - return old;*/ - - builder = gtk_builder_new (); - e_load_ui_builder_definition (builder, "mail-config.ui"); - - /* Security */ - emae_account_entry (emae, "pgp_key", E_ACCOUNT_PGP_KEY, builder); - emae_account_hash_algo_combo (emae, "pgp_hash_algo", E_ACCOUNT_PGP_HASH_ALGORITHM, builder); - emae_account_toggle (emae, "pgp_encrypt_to_self", E_ACCOUNT_PGP_ENCRYPT_TO_SELF, builder); - emae_account_toggle (emae, "pgp_always_sign", E_ACCOUNT_PGP_ALWAYS_SIGN, builder); - emae_account_toggle (emae, "pgp_no_imip_sign", E_ACCOUNT_PGP_NO_IMIP_SIGN, builder); - emae_account_toggle (emae, "pgp_always_trust", E_ACCOUNT_PGP_ALWAYS_TRUST, builder); - -#if defined (HAVE_NSS) && defined (ENABLE_SMIME) - /* TODO: this should handle its entry separately? */ - priv->smime_sign_key = emae_account_entry (emae, "smime_sign_key", E_ACCOUNT_SMIME_SIGN_KEY, builder); - priv->smime_sign_key_select = (GtkButton *)e_builder_get_widget (builder, "smime_sign_key_select"); - priv->smime_sign_key_clear = (GtkButton *)e_builder_get_widget (builder, "smime_sign_key_clear"); - g_signal_connect ( - priv->smime_sign_key_select, "clicked", - G_CALLBACK (smime_sign_key_select), emae); - g_signal_connect ( - priv->smime_sign_key_clear, "clicked", - G_CALLBACK (smime_sign_key_clear), emae); - - emae_account_hash_algo_combo (emae, "smime_hash_algo", E_ACCOUNT_SMIME_HASH_ALGORITHM, builder); - priv->smime_sign_default = emae_account_toggle (emae, "smime_sign_default", E_ACCOUNT_SMIME_SIGN_DEFAULT, builder); - - priv->smime_encrypt_key = emae_account_entry (emae, "smime_encrypt_key", E_ACCOUNT_SMIME_ENCRYPT_KEY, builder); - priv->smime_encrypt_key_select = (GtkButton *)e_builder_get_widget (builder, "smime_encrypt_key_select"); - priv->smime_encrypt_key_clear = (GtkButton *)e_builder_get_widget (builder, "smime_encrypt_key_clear"); - g_signal_connect ( - priv->smime_encrypt_key_select, "clicked", - G_CALLBACK (smime_encrypt_key_select), emae); - g_signal_connect ( - priv->smime_encrypt_key_clear, "clicked", - G_CALLBACK (smime_encrypt_key_clear), emae); - - priv->smime_encrypt_default = emae_account_toggle (emae, "smime_encrypt_default", E_ACCOUNT_SMIME_ENCRYPT_DEFAULT, builder); - priv->smime_encrypt_to_self = emae_account_toggle (emae, "smime_encrypt_to_self", E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, builder); - smime_changed (emae); -#else - { - /* Since we don't have NSS, hide the S/MIME config options */ - GtkWidget *frame; - - frame = e_builder_get_widget (builder, "smime_vbox"); - gtk_widget_destroy (frame); - } -#endif /* HAVE_NSS */ - - w = e_builder_get_widget (builder, item->label); - gtk_notebook_insert_page ( - GTK_NOTEBOOK (parent), w, - gtk_label_new (_("Security")), - position); - gtk_container_child_set ( - GTK_CONTAINER (parent), w, - "tab-fill", FALSE, "tab-expand", FALSE, NULL); - - g_object_unref (builder); - - return w; -} - -/* - * Allow some level of post creation customisation in plugins. - */ -GtkWidget * -em_account_editor_get_widget (EMAccountEditor *emae, - const gchar *name) -{ - GtkWidget *wid; - - wid = g_hash_table_lookup (emae->priv->widgets, name); - if (wid) - return wid; - - g_warning ("Mail account widget '%s' not found", name); - - return NULL; -} - -static GtkWidget * -emae_widget_glade (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - return em_account_editor_get_widget (data, item->label); -} - -/* plugin meta-data for "org.gnome.evolution.mail.config.accountEditor" */ -static EMConfigItem emae_editor_items[] = { - { E_CONFIG_BOOK, (gchar *) "" }, - { E_CONFIG_PAGE, (gchar *) "00.identity", (gchar *) "vboxIdentityBorder", emae_identity_page }, - { E_CONFIG_SECTION, (gchar *) "00.identity/00.name", (gchar *) "account_vbox", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/10.required", (gchar *) "identity-required-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/20.info", (gchar *) "identity-optional-table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "10.receive", (gchar *) "vboxSourceBorder", emae_receive_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/00.type", (gchar *) "source-type-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/10.config", (gchar *) "source-config-table", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/20.security", (gchar *) "source-security-vbox", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/30.auth", (gchar *) "source-auth-vbox", emae_widget_glade }, - - /* Most sections for this is auto-generated from the camel config */ - { E_CONFIG_PAGE, (gchar *) "20.receive_options", (gchar *) N_("Receiving Options"), }, - { E_CONFIG_SECTION_TABLE, (gchar *) "20.receive_options/10.mailcheck", (gchar *) N_("Checking for New Messages"), }, - { E_CONFIG_ITEM_TABLE, (gchar *) "20.receive_options/10.mailcheck/00.autocheck", NULL, emae_receive_options_item, }, - - { E_CONFIG_PAGE, (gchar *) "30.send", (gchar *) "vboxTransportBorder", emae_send_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/00.type", (gchar *) "transport-type-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/10.config", (gchar *) "transport-server-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/20.security", (gchar *) "transport-security-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/30.auth", (gchar *) "transport-auth-table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "40.defaults", (gchar *) "vboxFoldersBorder", emae_defaults_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "40.defaults/00.folders", (gchar *) "special-folders-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "40.defaults/10.composing", (gchar *) "composing-messages-table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "50.security", (gchar *) "vboxSecurityBorder", emae_security_page }, - /* 1x1 table (!) not vbox: { E_CONFIG_SECTION, "50.security/00.gpg", "table19", emae_widget_glade }, */ - /* table not vbox: { E_CONFIG_SECTION, "50.security/10.smime", "smime_table", emae_widget_glade }, */ - { 0 }, -}; -static gboolean emae_editor_items_translated = FALSE; - -static GtkWidget * -emae_review_page (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *priv = emae->priv; - GtkWidget *w; - GtkBuilder *builder; - - builder = gtk_builder_new (); - e_load_ui_builder_definition (builder, "mail-config.ui"); - - priv->review_name = (GtkLabel*) e_builder_get_widget (builder, "personal-name-entry"); - priv->review_email = (GtkLabel*) e_builder_get_widget (builder, "personal-email-entry"); - priv->receive_stype = (GtkLabel*) e_builder_get_widget (builder, "receive_server_type"); - priv->send_stype = (GtkLabel*) e_builder_get_widget (builder, "send_server_type"); - priv->receive_saddress = (GtkLabel*) e_builder_get_widget (builder, "receive_server_address"); - priv->send_saddress = (GtkLabel*) e_builder_get_widget (builder, "send_server_address"); - priv->receive_name = (GtkLabel*) e_builder_get_widget (builder, "receive_username"); - priv->send_name = (GtkLabel*) e_builder_get_widget (builder, "send_username"); - priv->receive_encryption = (GtkLabel*) e_builder_get_widget (builder, "receive_encryption"); - priv->send_encryption = (GtkLabel*) e_builder_get_widget (builder, "send_encryption"); - - w = e_builder_get_widget (builder, item->label); - priv->review_box = gtk_vbox_new (FALSE, 2); - gtk_widget_show (priv->review_box); - if (((EConfig *) priv->config)->type == E_CONFIG_ASSISTANT) { - GtkWidget *page; - - page = emae_create_basic_assistant_page ( - emae, GTK_ASSISTANT (parent), - "review_page", position); - - gtk_box_pack_start (GTK_BOX (page), w, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (page), priv->review_box, FALSE, FALSE, 0); - gtk_widget_reparent (priv->management_frame, page); - - w = page; - } - - return w; -} - -static GtkWidget * -emae_widget_assistant_page (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gint position, - gpointer data) -{ - EMAccountEditor *emae = (EMAccountEditor *) data; - - if (emae->type == EMAE_PAGES) - return NULL; - - return emae_create_basic_assistant_page ( - emae, GTK_ASSISTANT (parent), item->label, position); -} - -/* plugin meta-data for "org.gnome.evolution.mail.config.accountAssistant" */ -static EMConfigItem emae_assistant_items[] = { - { E_CONFIG_ASSISTANT, (gchar *) "" }, - { E_CONFIG_PAGE_START, (gchar *) "0.start", (gchar *) "start_page", emae_widget_assistant_page }, - - { E_CONFIG_PAGE, (gchar *) "00.identity", (gchar *) "vboxIdentityBorder", emae_identity_page }, - { E_CONFIG_SECTION, (gchar *) "00.identity/00.name", (gchar *) "account_vbox", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/10.required", (gchar *) "identity-required-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/20.info", (gchar *) "identity-optional-table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "10.receive", (gchar *) "vboxSourceBorder", emae_receive_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/00.type", (gchar *) "source-type-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/10.config", (gchar *) "source-config-table", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/20.security", (gchar *) "source-security-vbox", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/30.auth", (gchar *) "source-auth-vbox", emae_widget_glade }, - - /* Most sections for this is auto-generated fromt the camel config */ - { E_CONFIG_PAGE, (gchar *) "20.receive_options", (gchar *) N_("Receiving Options"), }, - { E_CONFIG_SECTION_TABLE, (gchar *) "20.receive_options/10.mailcheck", (gchar *) N_("Checking for New Messages"), }, - { E_CONFIG_ITEM_TABLE, (gchar *) "20.receive_options/10.mailcheck/00.autocheck", NULL, emae_receive_options_item, }, - - { E_CONFIG_PAGE, (gchar *) "30.send", (gchar *) "vboxTransportBorder", emae_send_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/00.type", (gchar *) "transport-type-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/10.config", (gchar *) "transport-server-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/20.security", (gchar *) "transport-security-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/30.auth", (gchar *) "transport-auth-table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "40.defaults", (gchar *) "vboxFoldersBorder", emae_defaults_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "40.defaults/00.folders", (gchar *) "special-folders-table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "40.defaults/10.composing", (gchar *) "composing-messages-table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "50.review", (gchar *) "vboxReviewBorder", emae_review_page }, - - { E_CONFIG_PAGE_FINISH, (gchar *) "999.end", (gchar *) "finish_page", emae_widget_assistant_page }, - { 0 }, -}; -static gboolean emae_assistant_items_translated = FALSE; - -static void -emae_free (EConfig *ec, - GSList *items, - gpointer data) -{ - g_slist_free (items); -} - -static void -emae_free_auto (EConfig *ec, - GSList *items, - gpointer data) -{ - GSList *l, *n; - - for (l = items; l;) { - struct _receive_options_item *item = l->data; - - n = g_slist_next (l); - g_free (item->item.path); - if (item->extra_table) - g_hash_table_destroy (item->extra_table); - g_free (item); - g_slist_free_1 (l); - l = n; - } -} - -static gboolean -emae_check_service_complete (EMAccountEditor *emae, - EMAccountEditorService *service) -{ - CamelProvider *provider = NULL; - const gchar *host = NULL; - const gchar *path = NULL; - const gchar *user = NULL; - gboolean have_host; - gboolean have_path; - gboolean have_user; - gboolean need_auth; - gboolean need_host; - gboolean need_path; - gboolean need_port; - gboolean need_user; - - if (service->protocol != NULL) - provider = camel_provider_get (service->protocol, NULL); - - if (provider == NULL) - return TRUE; - - if (CAMEL_IS_NETWORK_SETTINGS (service->settings)) { - CamelNetworkSettings *network_settings; - - network_settings = CAMEL_NETWORK_SETTINGS (service->settings); - host = camel_network_settings_get_host (network_settings); - user = camel_network_settings_get_user (network_settings); - } - - if (CAMEL_IS_LOCAL_SETTINGS (service->settings)) { - CamelLocalSettings *local_settings; - - local_settings = CAMEL_LOCAL_SETTINGS (service->settings); - path = camel_local_settings_get_path (local_settings); - } - - need_auth = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_AUTH); - need_host = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST); - need_path = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH); - need_port = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PORT); - need_user = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER); - - have_host = (host != NULL && *host != '\0'); - have_path = (path != NULL && *path != '\0'); - have_user = (user != NULL && *user != '\0'); - - if (need_host && !have_host) - return FALSE; - - if (need_port && !e_port_entry_is_valid (service->port)) - return FALSE; - - /* We only need the user if the service needs auth as well, i think */ - if (need_auth || service->requires_auth) - if (need_user && !have_user) - return FALSE; - - if (need_path && !have_path) - return FALSE; - - return TRUE; -} - -static ServerData * -emae_check_servers (const gchar *email) -{ - ServerData *sdata = g_new0 (ServerData, 1); - EmailProvider *provider = g_new0 (EmailProvider, 1); - gchar *dupe = g_strdup (email); - gchar *tmp; - - /* FIXME: Find a way to free the provider once given to account settings. */ - provider->email = (gchar *) email; - tmp = strchr (email, '@'); - tmp++; - provider->domain = tmp; - tmp = strchr (dupe, '@'); - *tmp = 0; - provider->username = (gchar *) g_quark_to_string (g_quark_from_string (dupe)); - g_free (dupe); - - if (!mail_guess_servers (provider)) { - g_free (provider); - g_free (sdata); - return NULL; - } - /*printf("Recv: %s\n%s(%s), %s by %s \n Send: %s\n%s(%s), %s by %s\n via %s to %s\n", - provider->recv_type, provider->recv_hostname, provider->recv_port, provider->recv_username, provider->recv_auth, - provider->send_type, provider->send_hostname, provider->send_port, provider->send_username, provider->send_auth, - provider->recv_socket_type, provider->send_socket_type); */ - - sdata->recv = provider->recv_hostname; - sdata->recv_port = provider->recv_port; - sdata->send = provider->send_hostname; - sdata->send_port = provider->send_port; - if (strcmp (provider->recv_type, "pop3") == 0) - sdata->proto = g_strdup ("pop"); - else if (strcmp (provider->recv_type, "imap") == 0) - sdata->proto = g_strdup ("imapx"); - else - sdata->proto = provider->recv_type; - if (provider->recv_socket_type) { - CamelNetworkSecurityMethod method; - - if (g_ascii_strcasecmp (provider->recv_socket_type, "SSL") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT; - else if (g_ascii_strcasecmp (provider->recv_socket_type, "secure") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT; - else if (g_ascii_strcasecmp (provider->recv_socket_type, "STARTTLS") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT; - else if (g_ascii_strcasecmp (provider->recv_socket_type, "TLS") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT; - else - method = CAMEL_NETWORK_SECURITY_METHOD_NONE; - - sdata->security_method = method; - sdata->recv_security_method = method; - } - - if (provider->send_socket_type) { - CamelNetworkSecurityMethod method; - - if (g_ascii_strcasecmp (provider->send_socket_type, "SSL") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT; - else if (g_ascii_strcasecmp (provider->send_socket_type, "secure") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT; - else if (g_ascii_strcasecmp (provider->send_socket_type, "STARTTLS") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT; - else if (g_ascii_strcasecmp (provider->send_socket_type, "TLS") == 0) - method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT; - else - method = CAMEL_NETWORK_SECURITY_METHOD_NONE; - - sdata->send_security_method = method; - } - - sdata->send_auth = g_ascii_strup (provider->send_auth, -1); - sdata->recv_auth = g_ascii_strup (provider->recv_auth, -1); - sdata->send_user = provider->send_username; - sdata->recv_user = provider->recv_username; - - g_free (provider); - - return sdata; -} - -static void -emae_destroy_widget (GtkWidget *widget) -{ - if (widget && GTK_IS_WIDGET (widget)) { - gtk_widget_destroy (widget); - widget = NULL; - } -} - -static gboolean -emae_display_name_in_use (EMAccountEditor *emae, - const gchar *display_name) -{ - EAccount *account; - EAccount *original_account; - - /* XXX Trivial for now, less so when we dump EAccount. */ - - account = e_get_account_by_name (display_name); - original_account = em_account_editor_get_original_account (emae); - - return (account != NULL && account != original_account); -} - -static void -emae_init_receive_page_for_new_account (EMAccountEditor *emae) -{ - EAccount *account; - const gchar *address; - gchar *user; - - account = em_account_editor_get_modified_account (emae); - address = e_account_get_string (account, E_ACCOUNT_ID_ADDRESS); - - /* Extract an initial username from the email address. */ - user = g_strdup (address); - if (user != NULL) { - gchar *cp = strchr (user, '@'); - if (cp != NULL) - *cp = '\0'; - } - - gtk_entry_set_text (emae->priv->source.username, user); - - g_free (user); -} - -static void -emae_init_receive_page_for_server_data (EMAccountEditor *emae) -{ - ServerData *sdata; - CamelNetworkSecurityMethod method; - gint port = 0; - - sdata = emae->priv->selected_server; - g_return_if_fail (sdata != NULL); - - if (sdata->recv_user == NULL) { - ; /* do nothing */ - } else if (*sdata->recv_user == '\0') { - ; /* do nothing */ - } else if (strcmp (sdata->recv_user, "@") == 0) { - ; /* do nothing */ - } else { - gtk_entry_set_text ( - emae->priv->source.username, - sdata->recv_user); - } - - if (sdata->recv_security_method != CAMEL_NETWORK_SECURITY_METHOD_NONE) - method = sdata->recv_security_method; - else - method = sdata->security_method; - - g_object_set ( - emae->priv->source.settings, - "security-method", method, NULL); - - emae->priv->source.protocol = sdata->proto; - - if (sdata->recv_port != NULL && *sdata->recv_port != '\0') - port = (gint) strtol (sdata->recv_port, NULL, 10); - - if (port > 0) - e_port_entry_set_port (emae->priv->source.port, port); - - gtk_toggle_button_set_active (emae->priv->source.remember, TRUE); - gtk_entry_set_text (emae->priv->source.hostname, sdata->recv); - - if (sdata->recv_auth != NULL && *sdata->recv_auth != '\0') - gtk_combo_box_set_active_id ( - emae->priv->source.authtype, - sdata->recv_auth); -} - -static void -emae_init_send_page_for_new_account (EMAccountEditor *emae) -{ - EAccount *account; - const gchar *address; - gchar *user; - - account = em_account_editor_get_modified_account (emae); - address = e_account_get_string (account, E_ACCOUNT_ID_ADDRESS); - - /* Extract an initial username from the email address. */ - user = g_strdup (address); - if (user != NULL) { - gchar *cp = strchr (user, '@'); - if (cp != NULL) - *cp = '\0'; - } - - gtk_entry_set_text (emae->priv->transport.username, user); - - g_free (user); -} - -static void -emae_init_send_page_for_server_data (EMAccountEditor *emae) -{ - ServerData *sdata; - CamelNetworkSecurityMethod method; - gint port = 0; - - sdata = emae->priv->selected_server; - g_return_if_fail (sdata != NULL); - - if (sdata->recv_user == NULL) { - ; /* do nothing */ - } else if (*sdata->recv_user == '\0') { - ; /* do nothing */ - } else if (strcmp (sdata->recv_user, "@") == 0) { - ; /* do nothing */ - } else { - gtk_entry_set_text ( - emae->priv->transport.username, - sdata->send_user); - } - - if (sdata->recv_security_method != CAMEL_NETWORK_SECURITY_METHOD_NONE) - method = sdata->recv_security_method; - else - method = sdata->security_method; - - g_object_set ( - emae->priv->transport.settings, - "security-method", method, NULL); - - emae->priv->transport.protocol = "smtp"; - - if (sdata->recv_port != NULL && *sdata->recv_port != '\0') - port = (gint) strtol (sdata->recv_port, NULL, 10); - - if (port > 0) - e_port_entry_set_port (emae->priv->source.port, port); - - gtk_toggle_button_set_active (emae->priv->transport.remember, TRUE); - gtk_toggle_button_set_active (emae->priv->transport.needs_auth, TRUE); - gtk_entry_set_text (emae->priv->transport.hostname, sdata->send); - - if (sdata->send_auth != NULL && *sdata->send_auth != '\0') - gtk_combo_box_set_active_id ( - emae->priv->source.authtype, - sdata->send_auth); - else - emae_authtype_changed ( - emae->priv->transport.authtype, - &emae->priv->transport); -} - -static void -emae_init_review_page (EMAccountEditor *emae) -{ - EAccount *account; - const gchar *address; - gchar *display_name; - gint ii = 1; - - account = em_account_editor_get_modified_account (emae); - address = e_account_get_string (account, E_ACCOUNT_ID_ADDRESS); - - display_name = g_strdup (address); - - /* Use the email address as the initial display name for the - * mail account. If necessary, append a number to the display - * name to make it unique among other mail accounts. */ - while (emae_display_name_in_use (emae, display_name)) { - g_free (display_name); - display_name = g_strdup_printf ("%s (%d)", address, ii++); - } - - gtk_entry_set_text (emae->priv->identity_entries[0], display_name); - - g_free (display_name); -} - -static void -emae_update_review_page (EMAccountEditor *emae) -{ - EAccount *account; - const gchar *name; - const gchar *address; - - account = em_account_editor_get_modified_account (emae); - name = e_account_get_string (account, E_ACCOUNT_ID_NAME); - address = e_account_get_string (account, E_ACCOUNT_ID_ADDRESS); - - gtk_label_set_text (emae->priv->review_name, name); - gtk_label_set_text (emae->priv->review_email, address); - - if (CAMEL_IS_NETWORK_SETTINGS (emae->priv->source.settings)) { - CamelNetworkSecurityMethod method; - const gchar *encryption; - const gchar *protocol; - gchar *host = NULL; - gchar *user = NULL; - - protocol = emae->priv->source.protocol; - - g_object_get ( - emae->priv->source.settings, - "host", &host, "user", &user, - "security-method", &method, NULL); - - switch (method) { - case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT: - encryption = _("Always (SSL)"); - break; - case CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT: - encryption = _("When possible (TLS)"); - break; - default: - encryption = _("Never"); - break; - } - - gtk_label_set_text (emae->priv->receive_stype, protocol); - gtk_label_set_text (emae->priv->receive_saddress, host); - gtk_label_set_text (emae->priv->receive_name, user); - gtk_label_set_text (emae->priv->receive_encryption, encryption); - - g_free (host); - g_free (user); - } - - if (CAMEL_IS_NETWORK_SETTINGS (emae->priv->transport.settings)) { - CamelNetworkSecurityMethod method; - const gchar *encryption; - const gchar *protocol; - gchar *host = NULL; - gchar *user = NULL; - - protocol = emae->priv->transport.protocol; - - g_object_get ( - emae->priv->transport.settings, - "host", &host, "user", &user, - "security-method", &method, NULL); - - switch (method) { - case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT: - encryption = _("Always (SSL)"); - break; - case CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT: - encryption = _("When possible (TLS)"); - break; - default: - encryption = _("Never"); - break; - } - - gtk_label_set_text (emae->priv->send_stype, protocol); - gtk_label_set_text (emae->priv->send_saddress, host); - gtk_label_set_text (emae->priv->send_name, user); - gtk_label_set_text (emae->priv->send_encryption, encryption); - - g_free (host); - g_free (user); - } -} - -static void -emae_update_review_page_for_google (EMAccountEditor *emae) -{ - GtkWidget *container; - GtkWidget *widget; - gchar *markup; - gboolean can_contacts, can_calendar; - - can_contacts = !emae->priv->gcontacts || - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (emae->priv->gcontacts)); - can_calendar = !emae->priv->calendar || - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (emae->priv->calendar)); - - emae_destroy_widget (emae->priv->gcontacts); - emae_destroy_widget (emae->priv->calendar); - emae_destroy_widget (emae->priv->account_label); - emae_destroy_widget (emae->priv->gmail_link); - - container = emae->priv->review_box; - - widget = gtk_label_new (NULL); - markup = g_markup_printf_escaped ( - "<span size=\"large\" weight=\"bold\">%s</span>", - _("Google account settings:")); - gtk_label_set_markup (GTK_LABEL (widget), markup); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->account_label = widget; - gtk_widget_show (widget); - g_free (markup); - - widget = gtk_check_button_new_with_mnemonic ( - _("Setup Google con_tacts with Evolution")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), can_contacts); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->gcontacts = widget; - gtk_widget_show (widget); - - widget = gtk_check_button_new_with_mnemonic ( - _("Setup Google ca_lendar with Evolution")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), can_calendar); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->calendar = widget; - gtk_widget_show (widget); - - widget = gtk_link_button_new_with_label ( - "https://mail.google.com/mail/?ui=2&shva=1#settings/fwdandpop", - _("You may need to enable IMAP access.")); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->gmail_link = widget; - gtk_widget_show (widget); -} - -static void -emae_update_review_page_for_yahoo (EMAccountEditor *emae) -{ - EAccount *account; - GtkWidget *container; - GtkWidget *widget; - GtkWidget *label; - gchar *markup; - gchar *name = NULL; - gboolean can_calendar, can_tasks; - - if (emae->priv->yahoo_cal_entry) { - name = g_strdup (gtk_entry_get_text (GTK_ENTRY (emae->priv->yahoo_cal_entry))); - } else { - account = em_account_editor_get_modified_account (emae); - name = g_strdup (e_account_get_string (account, E_ACCOUNT_ID_NAME)); - - g_strdelimit (name, " ", '_'); - } - - can_calendar = !emae->priv->calendar || - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (emae->priv->calendar)); - can_tasks = !emae->priv->tasks || - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (emae->priv->tasks)); - - emae_destroy_widget (emae->priv->calendar); - emae_destroy_widget (emae->priv->tasks); - emae_destroy_widget (emae->priv->info_label); - emae_destroy_widget (emae->priv->yahoo_cal_entry); - emae_destroy_widget (emae->priv->account_label); - emae_destroy_widget (emae->priv->yahoo_cal_box); - - container = emae->priv->review_box; - - widget = gtk_label_new (NULL); - markup = g_markup_printf_escaped ( - "<span size=\"large\" weight=\"bold\">%s</span>", - _("Yahoo! account settings:")); - gtk_label_set_markup (GTK_LABEL (widget), markup); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->account_label = widget; - gtk_widget_show (widget); - g_free (markup); - - widget = gtk_check_button_new_with_mnemonic ( - _("Setup _Yahoo! calendar with Evolution")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), can_calendar); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->calendar = widget; - gtk_widget_show (widget); - - widget = gtk_check_button_new_with_mnemonic ( - _("Setup Yahoo! _tasks with Evolution")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), can_tasks); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->tasks = widget; - gtk_widget_show (widget); - - widget = gtk_label_new ( - _("Yahoo! calendars are named as firstname_lastname. We have " - "tried to form the calendar name. Please confirm and " - "re-enter the calendar name, if it is not correct, or " - "change it later in calendar Properties.")); - gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); - gtk_label_set_line_wrap_mode (GTK_LABEL (widget), PANGO_WRAP_WORD); - gtk_label_set_selectable (GTK_LABEL (widget), TRUE); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->info_label = widget; - gtk_widget_show (widget); - - widget = gtk_hbox_new (FALSE, 12); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->yahoo_cal_box = widget; - gtk_widget_show (widget); - - container = widget; - - widget = gtk_label_new_with_mnemonic ( - _("Yahoo! Calen_dar name:")); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - label = widget; - - widget = gtk_entry_new (); - gtk_entry_set_text (GTK_ENTRY (widget), name); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - emae->priv->yahoo_cal_entry = widget; - gtk_widget_show (widget); - - g_free (name); -} - -static gboolean -emae_check_identity_complete (EMAccountEditor *emae) -{ - EAccount *account; - const gchar *name; - const gchar *address; - const gchar *reply_to; - - account = em_account_editor_get_modified_account (emae); - - name = e_account_get_string (account, E_ACCOUNT_ID_NAME); - address = e_account_get_string (account, E_ACCOUNT_ID_ADDRESS); - reply_to = e_account_get_string (account, E_ACCOUNT_ID_REPLY_TO); - - if (name == NULL || *name == '\0') - return FALSE; - - if (address == NULL || !is_email (address)) - return FALSE; - - /* An empty reply_to string is allowed. */ - if (reply_to != NULL && *reply_to != '\0' && !is_email (reply_to)) - return FALSE; - - return TRUE; -} - -static gboolean -emae_check_review_complete (EMAccountEditor *emae) -{ - EAccount *account; - const gchar *display_name; - - account = em_account_editor_get_modified_account (emae); - display_name = e_account_get_string (account, E_ACCOUNT_NAME); - - if (display_name == NULL || *display_name == '\0') - return FALSE; - - if (emae_display_name_in_use (emae, display_name)) - return FALSE; - - return TRUE; -} - -static gboolean -emae_check_complete (EConfig *ec, - const gchar *pageid, - gpointer data) -{ - EMAccountEditor *emae = data; - EAccount *account; - enum _e_config_t config_type; - gboolean refresh = FALSE; - gboolean new_account; - const gchar *address; - gchar *host = NULL; - gboolean ok = TRUE; - - config_type = ((EConfig *) emae->priv->config)->type; - new_account = (em_account_editor_get_original_account (emae) == NULL); - - account = em_account_editor_get_modified_account (emae); - address = e_account_get_string (account, E_ACCOUNT_ID_ADDRESS); - - if (CAMEL_IS_NETWORK_SETTINGS (emae->priv->source.settings)) - host = camel_network_settings_dup_host ( - CAMEL_NETWORK_SETTINGS (emae->priv->source.settings)); - - /* We use the page-check of various pages to 'prepare' or - * pre-load their values, only in the assistant. */ - - if (pageid == NULL || config_type != E_CONFIG_ASSISTANT) - goto skip_prepare; - - if (strcmp (pageid, "10.receive") == 0) { - if (!emae->priv->receive_set) { - - /* FIXME Do this asynchronously! */ - emae->priv->selected_server = - emae_check_servers (address); - - if (new_account) { - emae_init_receive_page_for_new_account (emae); - refresh = TRUE; - } - if (emae->priv->selected_server != NULL) - emae_init_receive_page_for_server_data (emae); - - emae->priv->receive_set = TRUE; - } - - } else if (strcmp (pageid, "30.send") == 0) { - if (!emae->priv->send_set) { - if (new_account) - emae_init_send_page_for_new_account (emae); - if (emae->priv->selected_server != NULL) { - emae_init_send_page_for_server_data (emae); - refresh = TRUE; - } - - emae->priv->send_set = TRUE; - } - - } else if (strcmp (pageid, "20.receive_options") == 0) { - if (!emae->priv->receive_opt_set) { - CamelProvider *provider; - - provider = emae_get_store_provider (emae); - - if (provider != NULL - && emae->priv->extra_provider != provider) { - emae->priv->extra_provider = provider; - emae_auto_detect (emae); - } - - emae->priv->receive_opt_set = TRUE; - } - - /* Review page is only shown in the assistant. */ - } else if (strcmp (pageid, "50.review") == 0) { - if (!emae->priv->review_set) { - emae_init_review_page (emae); - emae->priv->review_set = TRUE; - } - - emae_update_review_page (emae); - - /* Google and Yahoo get special treatment. */ - - emae->priv->is_gmail = FALSE; - emae->priv->is_yahoo = FALSE; - - if (e_util_utf8_strstrcase (host, "gmail")) { - emae->priv->is_gmail = TRUE; - emae_update_review_page_for_google (emae); - - } else if (e_util_utf8_strstrcase (host, "googlemail")) { - emae->priv->is_gmail = TRUE; - emae_update_review_page_for_google (emae); - - } else if (e_util_utf8_strstrcase (host, "yahoo.")) { - emae->priv->is_yahoo = TRUE; - emae_update_review_page_for_yahoo (emae); - - } else if (e_util_utf8_strstrcase (host, "ymail.")) { - emae->priv->is_yahoo = TRUE; - emae_update_review_page_for_yahoo (emae); - - } else if (e_util_utf8_strstrcase (host, "rocketmail.")) { - emae->priv->is_yahoo = TRUE; - emae_update_review_page_for_yahoo (emae); - } - } - -skip_prepare: - /* - * Setting a flag on the Account if it is marked as default. It is - * done in this way instead of using a temporary variable so as to - * keep track of which account is marked as default in case of - * editing multiple accounts at a time. - */ - if (gtk_toggle_button_get_active (emae->priv->default_account)) - g_object_set_data (G_OBJECT (account), "default_flagged", GINT_TO_POINTER(1)); - - if (ok && (pageid == NULL || strcmp (pageid, "00.identity") == 0)) - ok = emae_check_identity_complete (emae); - - if (ok && (pageid == NULL || strcmp (pageid, "10.receive") == 0)) { - if (emae->type != EMAE_NOTEBOOK && refresh) { - emae_refresh_providers ( - emae, &emae->priv->source); - emae_provider_changed ( - emae->priv->source.providers, - &emae->priv->source); - } - ok = emae_check_service_complete (emae, &emae->priv->source); - } - - if (ok && (pageid == NULL || strcmp (pageid, "30.send") == 0)) { - CamelProvider *provider; - - provider = emae_get_store_provider (emae); - if (!provider || !CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) { - if (emae->type != EMAE_NOTEBOOK && refresh) { - emae_refresh_providers ( - emae, &emae->priv->transport); - emae_provider_changed ( - emae->priv->transport.providers, - &emae->priv->transport); - } - ok = emae_check_service_complete ( - emae, &emae->priv->transport); - } - } - - if (ok && (pageid == NULL || strcmp (pageid, "50.review") == 0)) - ok = emae_check_review_complete (emae); - - g_free (host); - - return ok; -} - -gboolean -em_account_editor_check (EMAccountEditor *emae, - const gchar *page) -{ - return emae_check_complete ((EConfig *) emae->config, page, emae); -} - -static void -forget_password_if_needed (EAccount *original_account, - EAccount *modified_account, - e_account_item_t save_pass_itm, - e_account_item_t url_itm) -{ - const gchar *orig_url, *modif_url; - - g_return_if_fail (original_account != NULL); - g_return_if_fail (modified_account != NULL); - - orig_url = e_account_get_string (original_account, url_itm); - modif_url = e_account_get_string (modified_account, url_itm); - - if (orig_url && !*orig_url) - orig_url = NULL; - - if (modif_url && !*modif_url) - modif_url = NULL; - - if ((e_account_get_bool (original_account, save_pass_itm) != e_account_get_bool (modified_account, save_pass_itm) - && !e_account_get_bool (modified_account, save_pass_itm) && orig_url) || - (orig_url && !modif_url)) { - CamelURL *url; - gchar *url_str; - - url = camel_url_new (orig_url, NULL); - if (!url) - return; - - url_str = camel_url_to_string (url, CAMEL_URL_HIDE_PARAMS); - if (url_str) - e_passwords_forget_password (NULL, url_str); - - g_free (url_str); - camel_url_free (url); - } -} - -#define CALENDAR_CALDAV_URI "caldav://%s@www.google.com/calendar/dav/%s/events" -#define GMAIL_CALENDAR_LOCATION "://www.google.com/calendar/feeds/" -#define CALENDAR_DEFAULT_PATH "/private/full" -#define SELECTED_CALENDARS "selected-calendars" -#define YAHOO_CALENDAR_LOCATION "%s@caldav.calendar.yahoo.com/dav/%s/Calendar/%s" - -static gchar * -sanitize_user_mail (const gchar *user) -{ - if (!user) - return NULL; - - if (strstr (user, "%40") != NULL) { - return g_strdup (user); - } else if (!is_email (user)) { - return g_strconcat (user, "%40gmail.com", NULL); - } else { - gchar *tmp = g_malloc0 (sizeof (gchar) * (1 + strlen (user) + 2)); - gchar *at = strchr (user, '@'); - - strncpy (tmp, user, at - user); - strcat (tmp, "%40"); - strcat (tmp, at + 1); - - return tmp; - } -} - -static void -setup_google_addressbook (EMAccountEditor *emae) -{ - ESourceList *slist = NULL; - ESourceGroup *sgrp; - GSList *sources; - gboolean source_already_exists = FALSE; - CamelURL *url; - gchar * username; - EAccount *modified_account; - GError *error = NULL; - - if (!e_client_utils_get_sources (&slist, E_CLIENT_SOURCE_TYPE_CONTACTS, &error) || !slist) { - g_debug ("%s: Failed to get list of sources: %s", G_STRFUNC, error ? error->message : "Unknown error"); - g_clear_error (&error); - return; - } - - modified_account = em_account_editor_get_modified_account (emae); - sgrp = e_source_list_ensure_group (slist, _("Google"), "google://", TRUE); - url = emae_account_url (emae, E_ACCOUNT_SOURCE_URL); - username = g_strdup (url->user); - - sources = e_source_group_peek_sources (sgrp); - for (; sources; sources = sources->next) { - ESource *existing = (ESource *) sources->data; - if (!g_strcmp0 (e_source_peek_relative_uri (existing), username)) { - source_already_exists = TRUE; - break; - } - } - - if (!source_already_exists) { - ESource *abook; - - abook = e_source_new (e_account_get_string (modified_account, E_ACCOUNT_NAME), ""); - e_source_set_property (abook, "default", "true"); - e_source_set_property (abook, "offline_sync", "1"); - e_source_set_property (abook, "auth", "plain/password"); - e_source_set_property (abook, "use-ssl", "true"); - e_source_set_property (abook, "remember_password", "true"); - e_source_set_property (abook, "refresh-interval", "86400"); - e_source_set_property (abook, "completion", "true"); - e_source_set_property (abook, "username", username); - - e_source_group_add_source (sgrp, abook, -1); - e_source_set_relative_uri (abook, username); - e_source_list_sync (slist, NULL); - - g_object_unref (abook); - } - - g_free (username); - g_object_unref (sgrp); - g_object_unref (slist); -} - -static void -setup_google_calendar (EMAccountEditor *emae, - EClientSourceType source_type) -{ - ESourceList *slist = NULL; - ESourceGroup *sgrp; - ESource *calendar; - gchar *sanitize_uname, *username; - gchar *abs_uri, *rel_uri; - gchar **ids; - gint i; - GPtrArray *array; - CamelURL *url; - GSettings *settings; - EAccount *modified_account; - GError *error = NULL; - - if (!e_client_utils_get_sources (&slist, source_type, &error) || !slist) { - g_debug ("%s: Failed to get list of sources: %s", G_STRFUNC, error ? error->message : "Unknown error"); - g_clear_error (&error); - return; - } - - modified_account = em_account_editor_get_modified_account (emae); - sgrp = e_source_list_ensure_group (slist, _("Google"), "google://", TRUE); - url = emae_account_url (emae, E_ACCOUNT_SOURCE_URL); - username = g_strdup (url->user); - - calendar = e_source_new (e_account_get_string (modified_account, E_ACCOUNT_NAME), ""); - e_source_set_property (calendar, "ssl", "1"); - e_source_set_property (calendar, "refresh", "30"); - e_source_set_property (calendar, "auth", "1"); - e_source_set_property (calendar, "offline_sync", "1"); - e_source_set_property (calendar, "username", username); - e_source_set_property (calendar, "setup-username", username); - e_source_set_property (calendar, "default", "true"); - e_source_set_property (calendar, "alarm", "true"); - e_source_set_readonly (calendar, FALSE); - - if (source_type != E_CLIENT_SOURCE_TYPE_CONTACTS) - e_source_set_color_spec (calendar, "#CE9687"); - - e_source_group_add_source (sgrp, calendar, -1); - - sanitize_uname = sanitize_user_mail (username); - - abs_uri = g_strdup_printf (CALENDAR_CALDAV_URI, sanitize_uname, username); - e_source_set_absolute_uri (calendar, abs_uri); - - rel_uri = g_strconcat ("https", GMAIL_CALENDAR_LOCATION, sanitize_uname, CALENDAR_DEFAULT_PATH, NULL); - e_source_set_relative_uri (calendar, rel_uri); - - e_source_list_sync (slist, NULL); - - settings = g_settings_new ("org.gnome.evolution.calendar"); - ids = g_settings_get_strv (settings, SELECTED_CALENDARS); - array = g_ptr_array_new (); - for (i = 0; ids[i] != NULL; i++) - g_ptr_array_add (array, ids[i]); - g_ptr_array_add (array, (gpointer) e_source_get_uid (calendar)); - g_ptr_array_add (array, NULL); - g_settings_set_strv ( - settings, SELECTED_CALENDARS, - (const gchar * const *) array->pdata); - - g_strfreev (ids); - g_ptr_array_free (array, TRUE); - g_object_unref (settings); - g_free (username); - g_free (abs_uri); - g_free (rel_uri); - g_free (sanitize_uname); - g_object_unref (calendar); - g_object_unref (sgrp); - g_object_unref (slist); -} - -static void -setup_yahoo_calendar (EMAccountEditor *emae, - EClientSourceType source_type) -{ - ESourceList *slist = NULL; - ESourceGroup *sgrp; - ESource *calendar; - gchar *sanitize_uname; - gchar *abs_uri, *rel_uri; - const gchar *email; - GSettings *settings; - gchar **ids; - gint i; - GPtrArray *array; - EAccount *modified_account; - GError *error = NULL; - - if (!e_client_utils_get_sources (&slist, source_type, &error) || !slist) { - g_debug ("%s: Failed to get list of sources: %s", G_STRFUNC, error ? error->message : "Unknown error"); - g_clear_error (&error); - return; - } - - modified_account = em_account_editor_get_modified_account (emae); - email = e_account_get_string (modified_account, E_ACCOUNT_ID_ADDRESS); - sgrp = e_source_list_ensure_group (slist, _("CalDAV"), "caldav://", TRUE); - - calendar = e_source_new (e_account_get_string (modified_account, E_ACCOUNT_NAME), ""); - e_source_set_property (calendar, "ssl", "1"); - e_source_set_property (calendar, "refresh", "30"); - e_source_set_property (calendar, "refresh-type", "0"); - e_source_set_property (calendar, "auth", "1"); - e_source_set_property (calendar, "offline_sync", "1"); - e_source_set_property (calendar, "username", email); - e_source_set_property (calendar, "default", "true"); - e_source_set_property (calendar, "alarm", "true"); - e_source_set_readonly (calendar, FALSE); - - if (source_type != E_CLIENT_SOURCE_TYPE_CONTACTS) - e_source_set_color_spec (calendar, "#87CE8C"); - - sanitize_uname = sanitize_user_mail (email); - - abs_uri = g_strdup_printf ("caldav://%s@caldav.calendar.yahoo.com/dav/%s/Calendar/%s", - sanitize_uname, email, gtk_entry_get_text ((GtkEntry *) emae->priv->yahoo_cal_entry)); - rel_uri = g_strdup_printf (YAHOO_CALENDAR_LOCATION, sanitize_uname, email, gtk_entry_get_text ((GtkEntry *) emae->priv->yahoo_cal_entry)); - e_source_set_relative_uri (calendar, rel_uri); - - e_source_group_add_source (sgrp, calendar, -1); - e_source_list_sync (slist, NULL); - - settings = g_settings_new ("org.gnome.evolution.calendar"); - ids = g_settings_get_strv (settings, SELECTED_CALENDARS); - array = g_ptr_array_new (); - for (i = 0; ids[i] != NULL; i++) - g_ptr_array_add (array, ids[i]); - g_ptr_array_add (array, (gpointer) e_source_get_uid (calendar)); - g_ptr_array_add (array, NULL); - g_settings_set_strv ( - settings, SELECTED_CALENDARS, - (const gchar * const *) array->pdata); - - g_strfreev (ids); - g_ptr_array_free (array, TRUE); - g_object_unref (settings); - g_free (abs_uri); - g_free (rel_uri); - g_free (sanitize_uname); - g_object_unref (calendar); - g_object_unref (sgrp); - g_object_unref (slist); -} - -static void -copy_param (GQuark key_id, - gpointer data, - gpointer user_data) -{ - GData **copy = user_data; - - g_datalist_id_set_data_full (copy, key_id, g_strdup (data), g_free); -} - -static void -copy_original_url_parameters (CamelURL *copy_to_url, - const gchar *copy_from) -{ - CamelURL *url; - - g_return_if_fail (copy_to_url != NULL); - - if (!copy_from || !*copy_from) - return; - - url = camel_url_new (copy_from, NULL); - if (!url) - return; - - if (url->params) - g_datalist_foreach (&url->params, copy_param, ©_to_url->params); - - camel_url_free (url); -} - -static void -emae_commit (EConfig *ec, - EMAccountEditor *emae) -{ - EAccountList *accounts = e_get_account_list (); - EAccount *account; - EAccount *modified_account; - EAccount *original_account; - CamelProvider *provider; - CamelSettings *settings; - CamelURL *url; - const gchar *protocol; - gboolean requires_auth; - - modified_account = em_account_editor_get_modified_account (emae); - original_account = em_account_editor_get_original_account (emae); - provider = emae_get_store_provider (emae); - - /* check for google and yahoo specific settings */ - if (!original_account && emae->priv->is_gmail) { - if (gtk_toggle_button_get_active ((GtkToggleButton *) emae->priv->gcontacts)) - setup_google_addressbook (emae); - if (gtk_toggle_button_get_active ((GtkToggleButton *) emae->priv->calendar)) - setup_google_calendar (emae, E_CLIENT_SOURCE_TYPE_EVENTS); - } else if (!original_account && emae->priv->is_yahoo) { - if (gtk_toggle_button_get_active ((GtkToggleButton *) emae->priv->calendar)) - setup_yahoo_calendar (emae, E_CLIENT_SOURCE_TYPE_EVENTS); - if (gtk_toggle_button_get_active ((GtkToggleButton *) emae->priv->tasks)) - setup_yahoo_calendar (emae, E_CLIENT_SOURCE_TYPE_TASKS); - } - - /* Do some last minute tweaking. */ - - settings = emae->priv->source.settings; - requires_auth = emae_get_store_requires_auth (emae); - - /* Override the selected authentication mechanism name if - * authentication is not required for the storage service. */ - if (CAMEL_IS_NETWORK_SETTINGS (settings) && !requires_auth) - g_object_set (settings, "auth-mechanism", NULL, NULL); - - settings = emae->priv->transport.settings; - requires_auth = emae_get_transport_requires_auth (emae); - - /* Override the selected authentication mechanism name if - * authentication is not required for the transport service. */ - if (CAMEL_IS_NETWORK_SETTINGS (settings) && !requires_auth) - g_object_set (settings, "auth-mechanism", NULL, NULL); - - /* Dump the storage service settings to a URL string. */ - - url = camel_url_new ("dummy://", NULL); - - protocol = emae->priv->source.protocol; - settings = emae->priv->source.settings; - - if (g_strcmp0 (protocol, "none") == 0) { - g_free (modified_account->source->url); - modified_account->source->url = g_strdup (""); - } else { - if (protocol != NULL) - camel_url_set_protocol (url, protocol); - - /* the CamelSaslXOAUTH stores its data into parameters - * unknown to settings, thus copy these first and overwrite - * those known during save */ - copy_original_url_parameters (url, modified_account->source->url); - - if (settings != NULL) - camel_settings_save_to_url (settings, url); - - g_free (modified_account->source->url); - modified_account->source->url = camel_url_to_string (url, 0); - } - - camel_url_free (url); - - /* Dump the transport service settings to a URL string. */ - - url = camel_url_new ("dummy://", NULL); - - if (!provider || !CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) - protocol = emae->priv->transport.protocol; - - settings = emae->priv->transport.settings; - - if (protocol != NULL) - camel_url_set_protocol (url, protocol); - - /* the CamelSaslXOAUTH stores its data into parameters - * unknown to settings, thus copy these first and overwrite - * those known during save */ - copy_original_url_parameters (url, modified_account->transport->url); - - if (settings != NULL) - camel_settings_save_to_url (settings, url); - - g_free (modified_account->transport->url); - modified_account->transport->url = camel_url_to_string (url, 0); - - camel_url_free (url); - - if (original_account != NULL) { - forget_password_if_needed (original_account, modified_account, E_ACCOUNT_SOURCE_SAVE_PASSWD, E_ACCOUNT_SOURCE_URL); - forget_password_if_needed (original_account, modified_account, E_ACCOUNT_TRANSPORT_SAVE_PASSWD, E_ACCOUNT_TRANSPORT_URL); - - e_account_import (original_account, modified_account); - account = original_account; - e_account_list_change (accounts, account); - } else { - e_account_list_add (accounts, modified_account); - account = modified_account; - } - - if (gtk_toggle_button_get_active (emae->priv->default_account)) { - EMailBackend *backend; - EMailSession *session; - EMailAccountStore *store; - CamelService *service; - - backend = em_account_editor_get_backend (emae); - session = e_mail_backend_get_session (backend); - - service = camel_session_get_service ( - CAMEL_SESSION (session), account->uid); - - store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session)); - e_mail_account_store_set_default_service (store, service); - } - - e_account_list_save (accounts); -} - -void -em_account_editor_commit (EMAccountEditor *emae) -{ - emae_commit (E_CONFIG (emae->config), emae); -} - -static void -em_account_editor_construct (EMAccountEditor *emae, - EMAccountEditorType type, - const gchar *id) -{ - EMAccountEditorPrivate *priv = emae->priv; - gint i, index; - GSList *l; - GList *prov; - EMConfig *ec; - EMConfigTargetSettings *target; - GHashTable *have; - EConfigItem *items; - - emae->type = type; - - if (type == EMAE_NOTEBOOK) { - ec = em_config_new (E_CONFIG_BOOK, id); - items = emae_editor_items; - if (!emae_editor_items_translated) { - for (i = 0; items[i].path; i++) { - if (items[i].label) - items[i].label = gettext (items[i].label); - } - emae_editor_items_translated = TRUE; - } - } else { - ec = em_config_new (E_CONFIG_ASSISTANT, id); - items = emae_assistant_items; - if (!emae_assistant_items_translated) { - for (i = 0; items[i].path; i++) { - if (items[i].label) - items[i].label = _(items[i].label); - } - emae_assistant_items_translated = TRUE; - } - } - - /* Connect "after" to let plugins go first. */ - g_signal_connect_after ( - ec, "commit", - G_CALLBACK (emae_commit), emae); - - g_object_weak_ref (G_OBJECT (ec), emae_config_gone_cb, emae); - - emae->config = priv->config = ec; - l = NULL; - for (i = 0; items[i].path; i++) - l = g_slist_prepend (l, &items[i]); - e_config_add_items ((EConfig *) ec, l, emae_free, emae); - - /* This is kinda yuck, we're dynamically mapping from the 'old style' extensibility api to the new one */ - l = NULL; - have = g_hash_table_new (g_str_hash, g_str_equal); - index = 20; - for (prov = priv->providers; prov; prov = g_list_next (prov)) { - CamelProviderConfEntry *entries = ((CamelProvider *) prov->data)->extra_conf; - - for (i = 0; entries && entries[i].type != CAMEL_PROVIDER_CONF_END; i++) { - struct _receive_options_item *item; - const gchar *name = entries[i].name; - gint myindex = index; - - if (entries[i].type != CAMEL_PROVIDER_CONF_SECTION_START - || name == NULL - || g_hash_table_lookup (have, name)) - continue; - - /* override mailcheck since we also insert our own mailcheck item at this index */ - if (name && !strcmp (name, "mailcheck")) - myindex = 10; - - item = g_malloc0 (sizeof (*item)); - item->item.type = E_CONFIG_SECTION_TABLE; - item->item.path = g_strdup_printf ("20.receive_options/%02d.%s", myindex, name?name:"unnamed"); - item->item.label = g_strdup (entries[i].text); - - l = g_slist_prepend (l, item); - - item = g_malloc0 (sizeof (*item)); - item->item.type = E_CONFIG_ITEM_TABLE; - item->item.path = g_strdup_printf ("20.receive_options/%02d.%s/80.camelitem", myindex, name?name:"unnamed"); - item->item.factory = emae_receive_options_extra_item; - item->item.user_data = g_strdup (entries[i].name); - - l = g_slist_prepend (l, item); - - index += 10; - g_hash_table_insert (have, (gpointer) entries[i].name, have); - } - } - g_hash_table_destroy (have); - e_config_add_items ((EConfig *) ec, l, emae_free_auto, emae); - priv->extra_items = l; - - e_config_add_page_check ((EConfig *) ec, NULL, emae_check_complete, emae); - - target = em_config_target_new_settings ( - ec, - emae->priv->modified_account->id->address, - emae->priv->source.protocol, - emae->priv->source.settings, - emae->priv->transport.protocol, - emae->priv->transport.settings); - e_config_set_target ((EConfig *) ec, (EConfigTarget *) target); -} - diff --git a/mail/em-account-editor.h b/mail/em-account-editor.h deleted file mode 100644 index 18d4b91f9e..0000000000 --- a/mail/em-account-editor.h +++ /dev/null @@ -1,124 +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> - * Dan Winship <danw@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EM_ACCOUNT_EDITOR_H -#define EM_ACCOUNT_EDITOR_H - -#include <gtk/gtk.h> -#include <mail/em-config.h> -#include <mail/e-mail-backend.h> - -#include <libedataserver/e-account.h> - -/* Standard GObject macros */ -#define EM_TYPE_ACCOUNT_EDITOR \ - (em_account_editor_get_type ()) -#define EM_ACCOUNT_EDITOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), EM_TYPE_ACCOUNT_EDITOR, EMAccountEditor)) -#define EM_ACCOUNT_EDITOR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), EM_TYPE_ACCOUNT_EDITOR, EMAccountEditorClass)) -#define EM_IS_ACCOUNT_EDITOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), EM_TYPE_ACCOUNT_EDITOR)) -#define EM_IS_ACCOUNT_EDITOR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), EM_TYPE_ACCOUNT_EDITOR)) -#define EM_ACCOUNT_EDITOR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), EM_TYPE_ACCOUNT_EDITOR, EMAccountEditorClass)) - -G_BEGIN_DECLS - -typedef struct _EMAccountEditor EMAccountEditor; -typedef struct _EMAccountEditorClass EMAccountEditorClass; -typedef struct _EMAccountEditorPrivate EMAccountEditorPrivate; - -typedef struct _server_data ServerData; -struct _server_data { - const gchar *key; - const gchar *recv; - const gchar *send; - const gchar *proto; - CamelNetworkSecurityMethod security_method; - const gchar *send_user; - const gchar *recv_user; - const gchar *send_port; - const gchar *recv_port; - CamelNetworkSecurityMethod send_security_method; - CamelNetworkSecurityMethod recv_security_method; - const gchar *send_auth; - const gchar *recv_auth; -}; - -typedef enum { - EMAE_NOTEBOOK, - EMAE_ASSISTANT, - EMAE_PAGES -} EMAccountEditorType; - -struct _EMAccountEditor { - GObject parent; - - EMAccountEditorPrivate *priv; - - EMAccountEditorType type; - - EMConfig *config; /* driver object */ - - GtkWidget **pages; /* Pages for Anjal's page type editor */ - - guint do_signature:1; /* allow editing signature */ -}; - -struct _EMAccountEditorClass { - GObjectClass parent_class; -}; - -GType em_account_editor_get_type (void); -EMAccountEditor * - em_account_editor_new (EAccount *account, - EMAccountEditorType type, - EMailBackend *backend, - const gchar *id); -EMAccountEditor * - em_account_editor_new_for_pages (EAccount *account, - EMAccountEditorType type, - EMailBackend *backend, - const gchar *id, - GtkWidget **pages); -EMailBackend * em_account_editor_get_backend (EMAccountEditor *emae); -EAccount * em_account_editor_get_modified_account - (EMAccountEditor *emae); -EAccount * em_account_editor_get_original_account - (EMAccountEditor *emae); -void em_account_editor_commit (EMAccountEditor *emae); -gboolean em_account_editor_check (EMAccountEditor *emae, - const gchar *page); -GtkWidget * em_account_editor_get_widget (EMAccountEditor *emae, - const gchar *name); - -G_END_DECLS - -#endif /* EM_ACCOUNT_EDITOR_H */ diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 7ea31635e6..a39a5f834d 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -31,17 +31,22 @@ #include <glib/gi18n.h> #include <libedataserver/e-data-server-util.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-composition.h> +#include <libedataserver/e-source-mail-identity.h> +#include <libedataserver/e-source-mail-submission.h> +#include <libedataserver/e-source-mdn.h> #include <libevolution-utils/e-alert-dialog.h> #include <libevolution-utils/e-alert-sink.h> #include <e-util/e-util.h> -#include <libemail-utils/e-account-utils.h> #include <libemail-utils/mail-mt.h> #include <libemail-engine/e-mail-folder-utils.h> #include <libemail-engine/e-mail-session.h> #include <libemail-engine/e-mail-session-utils.h> +#include <libemail-engine/e-mail-utils.h> #include <libemail-engine/mail-ops.h> #include <libemail-engine/mail-tools.h> @@ -366,23 +371,31 @@ finished: } static gboolean -composer_presend_check_account (EMsgComposer *composer, - EMailSession *session) +composer_presend_check_identity (EMsgComposer *composer, + EMailSession *session) { EComposerHeaderTable *table; - EAccount *account; - gboolean check_passed; + ESourceRegistry *registry; + ESource *source; + const gchar *uid; + gboolean success = TRUE; table = e_msg_composer_get_header_table (composer); - account = e_composer_header_table_get_account (table); - check_passed = (account != NULL && account->enabled); + registry = e_composer_header_table_get_registry (table); + uid = e_composer_header_table_get_identity_uid (table); + source = e_source_registry_ref_source (registry, uid); + g_return_val_if_fail (source != NULL, FALSE); - if (!check_passed) + if (!e_source_get_enabled (source)) { e_alert_submit ( E_ALERT_SINK (composer), "mail:send-no-account-enabled", NULL); + success = FALSE; + } - return check_passed; + g_object_unref (source); + + return success; } static gboolean @@ -812,9 +825,11 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer, { AsyncContext *context; EComposerHeaderTable *table; - const gchar *drafts_folder_uri = NULL; + ESourceRegistry *registry; + ESource *source; const gchar *local_drafts_folder_uri; - EAccount *account; + const gchar *identity_uid; + gchar *drafts_folder_uri = NULL; context = g_slice_new0 (AsyncContext); context->message = g_object_ref (message); @@ -822,18 +837,30 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer, context->composer = g_object_ref (composer); context->activity = g_object_ref (activity); - local_drafts_folder_uri = - e_mail_session_get_local_folder_uri ( - session, E_MAIL_LOCAL_FOLDER_DRAFTS); - table = e_msg_composer_get_header_table (composer); - account = e_composer_header_table_get_account (table); - if (account != NULL && account->enabled) - drafts_folder_uri = account->drafts_folder_uri; + registry = e_composer_header_table_get_registry (table); + identity_uid = e_composer_header_table_get_identity_uid (table); + source = e_source_registry_ref_source (registry, identity_uid); + + /* Get the selected identity's preferred Drafts folder. */ + if (source != NULL) { + ESourceMailComposition *extension; + const gchar *extension_name; + gchar *uri; + + extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION; + extension = e_source_get_extension (source, extension_name); + uri = e_source_mail_composition_dup_drafts_folder (extension); + + drafts_folder_uri = uri; - if (g_strcmp0 (drafts_folder_uri, local_drafts_folder_uri) == 0) - drafts_folder_uri = NULL; + g_object_unref (source); + } + + local_drafts_folder_uri = + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_DRAFTS); if (drafts_folder_uri == NULL) { composer_save_to_drafts_append_mail (context, NULL); @@ -849,6 +876,8 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer, G_PRIORITY_DEFAULT, cancellable, (GAsyncReadyCallback) composer_save_to_drafts_got_folder, context); + + g_free (drafts_folder_uri); } } @@ -976,22 +1005,23 @@ create_new_composer (EShell *shell, CamelFolder *folder) { EMsgComposer *composer; + ESourceRegistry *registry; EComposerHeaderTable *table; - EAccount *account = NULL; + ESource *source = NULL; + gchar *identity = NULL; composer = e_msg_composer_new (shell); table = e_msg_composer_get_header_table (composer); + registry = e_composer_header_table_get_registry (table); if (folder != NULL) { CamelStore *store; - const gchar *uid; gchar *folder_uri; GList *list; store = camel_folder_get_parent_store (folder); - uid = camel_service_get_uid (CAMEL_SERVICE (store)); - account = e_get_account_by_uid (uid); + source = em_utils_ref_mail_identity_for_store (registry, store); folder_uri = e_mail_folder_uri_from_folder (folder); @@ -1002,8 +1032,15 @@ create_new_composer (EShell *shell, g_free (folder_uri); } - e_composer_header_table_set_account (table, account); + if (source != NULL) { + identity = e_source_dup_uid (source); + g_object_unref (source); + } + e_composer_header_table_set_subject (table, subject); + e_composer_header_table_set_identity_uid (table, identity); + + g_free (identity); return composer; } @@ -1049,8 +1086,8 @@ em_utils_compose_new_message_with_mailto (EShell *shell, CamelFolder *folder) { EMsgComposer *composer; + ESourceRegistry *registry; EComposerHeaderTable *table; - CamelService *service = NULL; g_return_val_if_fail (E_IS_SHELL (shell), NULL); @@ -1063,25 +1100,29 @@ em_utils_compose_new_message_with_mailto (EShell *shell, composer = e_msg_composer_new (shell); table = e_msg_composer_get_header_table (composer); + registry = e_composer_header_table_get_registry (table); + + composer_set_no_change (composer); + + gtk_window_present (GTK_WINDOW (composer)); + + /* If a CamelFolder was given, we need to backtrack and find + * the corresponding ESource with a Mail Identity extension. */ if (folder != NULL) { + ESource *source; CamelStore *store; store = camel_folder_get_parent_store (folder); - service = CAMEL_SERVICE (store); - } - - if (service != NULL) { - const gchar *display_name; + source = em_utils_ref_mail_identity_for_store (registry, store); - display_name = camel_service_get_display_name (service); - e_composer_header_table_set_account_name (table, display_name); + if (source != NULL) { + const gchar *uid = e_source_get_uid (source); + e_composer_header_table_set_identity_uid (table, uid); + g_object_unref (source); + } } - composer_set_no_change (composer); - - gtk_window_present (GTK_WINDOW (composer)); - return composer; } @@ -1302,6 +1343,7 @@ em_utils_edit_message (EShell *shell, const gchar *message_uid) { EMsgComposer *composer; + ESourceRegistry *registry; gboolean folder_is_drafts; gboolean folder_is_outbox; gboolean folder_is_templates; @@ -1310,9 +1352,10 @@ em_utils_edit_message (EShell *shell, g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL); g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL); - folder_is_drafts = em_utils_folder_is_drafts (folder); - folder_is_outbox = em_utils_folder_is_outbox (folder); - folder_is_templates = em_utils_folder_is_templates (folder); + registry = e_shell_get_registry (shell); + folder_is_drafts = em_utils_folder_is_drafts (registry, folder); + folder_is_outbox = em_utils_folder_is_outbox (registry, folder); + folder_is_templates = em_utils_folder_is_templates (registry, folder); /* Template specific code follows. */ if (folder_is_templates) { @@ -1339,19 +1382,23 @@ em_utils_edit_message (EShell *shell, } composer = e_msg_composer_new_with_message (shell, message, NULL); - if (folder && !folder_is_templates) { + if (!folder_is_templates) { EComposerHeaderTable *table; - EAccount *account; + ESource *source; CamelStore *store; - const gchar *uid; gchar *folder_uri; GList *list; table = e_msg_composer_get_header_table (composer); store = camel_folder_get_parent_store (folder); - uid = camel_service_get_uid (CAMEL_SERVICE (store)); - account = e_get_account_by_uid (uid); + source = em_utils_ref_mail_identity_for_store (registry, store); + + if (source != NULL) { + const gchar *uid = e_source_get_uid (source); + e_composer_header_table_set_identity_uid (table, uid); + g_object_unref (source); + } folder_uri = e_mail_folder_uri_from_folder (folder); @@ -1360,8 +1407,6 @@ em_utils_edit_message (EShell *shell, g_list_free (list); g_free (folder_uri); - - e_composer_header_table_set_account (table, account); } e_msg_composer_remove_header ( @@ -1902,8 +1947,11 @@ static EMsgComposer * redirect_get_composer (EShell *shell, CamelMimeMessage *message) { + EMsgComposer *composer; + ESourceRegistry *registry; CamelMedium *medium; - EAccount *account; + ESource *source; + gchar *identity_uid = NULL; medium = CAMEL_MEDIUM (message); @@ -1919,10 +1967,23 @@ redirect_get_composer (EShell *shell, while (camel_medium_get_header (medium, "Resent-Bcc")) camel_medium_remove_header (medium, "Resent-Bcc"); - account = em_utils_guess_account_with_recipients (message, NULL); + registry = e_shell_get_registry (shell); + + /* This returns a new ESource reference. */ + source = em_utils_guess_mail_identity_with_recipients ( + registry, message, NULL); + + if (source != NULL) { + identity_uid = e_source_dup_uid (source); + g_object_unref (source); + } - return e_msg_composer_new_redirect ( - shell, message, account ? account->name : NULL, NULL); + composer = e_msg_composer_new_redirect ( + shell, message, identity_uid, NULL); + + g_free (identity_uid); + + return composer; } /** @@ -1989,7 +2050,7 @@ em_utils_camel_address_to_destination (CamelInternetAddress *iaddr) static EMsgComposer * reply_get_composer (EShell *shell, CamelMimeMessage *message, - EAccount *account, + const gchar *identity_uid, CamelInternetAddress *to, CamelInternetAddress *cc, CamelFolder *folder, @@ -2030,9 +2091,9 @@ reply_get_composer (EShell *shell, } table = e_msg_composer_get_header_table (composer); - e_composer_header_table_set_account (table, account); e_composer_header_table_set_subject (table, subject); e_composer_header_table_set_destinations_to (table, tov); + e_composer_header_table_set_identity_uid (table, identity_uid); /* Add destinations instead of setting, so we don't remove * automatic CC addresses that have already been added. */ @@ -2311,64 +2372,6 @@ get_reply_recipient (CamelMimeMessage *message, } -static GHashTable * -generate_recipient_hash (void) -{ - GHashTable *rcpt_hash; - EAccount *account, *def; - EAccountList *account_list; - EIterator *iterator; - - account_list = e_get_account_list (); - rcpt_hash = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - - def = e_get_default_account (); - - iterator = e_list_get_iterator (E_LIST (account_list)); - - while (e_iterator_is_valid (iterator)) { - account = (EAccount *) e_iterator_get (iterator); - - if (account->id->address) { - EAccount *acnt; - - /* Accounts with identical email addresses that are - * enabled take precedence over the accounts that - * aren't. If all accounts with matching email - * addresses are disabled, then the first one in - * the list takes precedence. The default account - * always takes precedence no matter what. */ - acnt = g_hash_table_lookup ( - rcpt_hash, account->id->address); - if (acnt && acnt != def && !acnt->enabled && account->enabled) { - g_hash_table_remove ( - rcpt_hash, acnt->id->address); - acnt = NULL; - } - - if (!acnt) - g_hash_table_insert ( - rcpt_hash, (gchar *) - account->id->address, - (gpointer) account); - } - - e_iterator_next (iterator); - } - - g_object_unref (iterator); - - /* The default account has to be there if none - * of the enabled accounts are present. */ - if (g_hash_table_size (rcpt_hash) == 0 && def && def->id->address) - g_hash_table_insert ( - rcpt_hash, (gchar *) - def->id->address, - (gpointer) def); - - return rcpt_hash; -} - static void concat_unique_addrs (CamelInternetAddress *dest, CamelInternetAddress *src, @@ -2385,8 +2388,91 @@ concat_unique_addrs (CamelInternetAddress *dest, } } +static GHashTable * +generate_recipient_hash (ESourceRegistry *registry) +{ + GHashTable *rcpt_hash; + ESource *default_source; + GList *list, *link; + const gchar *extension_name; + + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + rcpt_hash = g_hash_table_new ( + (GHashFunc) camel_strcase_hash, + (GEqualFunc) camel_strcase_equal); + + default_source = e_source_registry_ref_default_mail_identity (registry); + + 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)) { + ESource *source = E_SOURCE (link->data); + ESource *cached_source; + ESourceMailIdentity *extension; + const gchar *address; + gboolean insert_source; + gboolean cached_is_default; + gboolean cached_is_enabled; + gboolean source_is_default; + gboolean source_is_enabled; + + /* No default mail identity implies there are no mail + * identities at all and so we should never get here. */ + g_warn_if_fail (default_source != NULL); + + source_is_default = e_source_equal (source, default_source); + source_is_enabled = e_source_get_enabled (source); + + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + extension = e_source_get_extension (source, extension_name); + + address = e_source_mail_identity_get_address (extension); + + if (address == NULL) + continue; + + cached_source = g_hash_table_lookup (rcpt_hash, address); + + if (cached_source != NULL) { + cached_is_default = e_source_equal ( + cached_source, default_source); + cached_is_enabled = + e_source_get_enabled (cached_source); + } else { + cached_is_default = FALSE; + cached_is_enabled = FALSE; + } + + /* Accounts with identical email addresses that are enabled + * take precedence over disabled accounts. If all accounts + * with matching email addresses are disabled, the first + * one in the list takes precedence. The default account + * always takes precedence no matter what. */ + insert_source = + source_is_default || + cached_source == NULL || + (source_is_enabled && + !cached_is_enabled && + !cached_is_default); + + if (insert_source) + g_hash_table_insert ( + rcpt_hash, (gchar *) address, source); + } + + g_list_free_full (list, (GDestroyNotify) g_object_unref); + + if (default_source != NULL) + g_object_unref (default_source); + + return rcpt_hash; +} + void -em_utils_get_reply_all (CamelMimeMessage *message, +em_utils_get_reply_all (ESourceRegistry *registry, + CamelMimeMessage *message, CamelInternetAddress *to, CamelInternetAddress *cc, CamelNNTPAddress *postto) @@ -2399,6 +2485,7 @@ em_utils_get_reply_all (CamelMimeMessage *message, const gchar *posthdr = NULL; GHashTable *rcpt_hash; + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); g_return_if_fail (CAMEL_IS_INTERNET_ADDRESS (to)); g_return_if_fail (CAMEL_IS_INTERNET_ADDRESS (cc)); @@ -2415,7 +2502,7 @@ em_utils_get_reply_all (CamelMimeMessage *message, if (postto != NULL && posthdr != NULL) camel_address_decode (CAMEL_ADDRESS (postto), posthdr); - rcpt_hash = generate_recipient_hash (); + rcpt_hash = generate_recipient_hash (registry); reply_to = get_reply_to (message); to_addrs = camel_mime_message_get_recipients ( @@ -2804,10 +2891,12 @@ em_utils_reply_to_message (EShell *shell, EMFormat *source_formatter, CamelInternetAddress *address) { + ESourceRegistry *registry; CamelInternetAddress *to, *cc; CamelNNTPAddress *postto = NULL; EMsgComposer *composer; - EAccount *account; + ESource *source; + gchar *identity_uid = NULL; guint32 flags; g_return_val_if_fail (E_IS_SHELL (shell), NULL); @@ -2816,11 +2905,20 @@ em_utils_reply_to_message (EShell *shell, to = camel_internet_address_new (); cc = camel_internet_address_new (); - account = em_utils_guess_account_with_recipients (message, folder); + registry = e_shell_get_registry (shell); + + /* This returns a new ESource reference. */ + source = em_utils_guess_mail_identity_with_recipients ( + registry, message, folder); + if (source != NULL) { + identity_uid = e_source_dup_uid (source); + g_object_unref (source); + } + flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN; if (!address && (type == E_MAIL_REPLY_TO_FROM || type == E_MAIL_REPLY_TO_SENDER) && - folder && em_utils_folder_is_sent (folder)) + folder && em_utils_folder_is_sent (registry, folder)) type = E_MAIL_REPLY_TO_ALL; switch (type) { @@ -2852,12 +2950,12 @@ em_utils_reply_to_message (EShell *shell, if (folder) postto = camel_nntp_address_new (); - em_utils_get_reply_all (message, to, cc, postto); + em_utils_get_reply_all (registry, message, to, cc, postto); break; } composer = reply_get_composer ( - shell, message, account, to, cc, folder, postto); + shell, message, identity_uid, to, cc, folder, postto); e_msg_composer_add_message_attachments (composer, message, TRUE); if (postto) @@ -2882,6 +2980,8 @@ em_utils_reply_to_message (EShell *shell, gtk_widget_show (GTK_WIDGET (composer)); + g_free (identity_uid); + return composer; } @@ -2969,7 +3069,7 @@ em_configure_new_composer (EMsgComposer *composer, g_signal_connect ( composer, "presend", - G_CALLBACK (composer_presend_check_account), session); + G_CALLBACK (composer_presend_check_identity), session); g_signal_connect ( composer, "presend", diff --git a/mail/em-composer-utils.h b/mail/em-composer-utils.h index 865254ca31..a525cec2a2 100644 --- a/mail/em-composer-utils.h +++ b/mail/em-composer-utils.h @@ -67,7 +67,8 @@ gboolean em_utils_is_munged_list_message (CamelMimeMessage *message); void em_utils_get_reply_sender (CamelMimeMessage *message, CamelInternetAddress *to, CamelNNTPAddress *postto); -void em_utils_get_reply_all (CamelMimeMessage *message, +void em_utils_get_reply_all (ESourceRegistry *registry, + CamelMimeMessage *message, CamelInternetAddress *to, CamelInternetAddress *cc, CamelNNTPAddress *postto); diff --git a/mail/em-filter-source-element.c b/mail/em-filter-source-element.c index 5848f938db..4362b11dc2 100644 --- a/mail/em-filter-source-element.c +++ b/mail/em-filter-source-element.c @@ -32,23 +32,18 @@ #include <gtk/gtk.h> #include <camel/camel.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-identity.h> + +#include <shell/e-shell.h> #include <filter/e-filter-part.h> -#include <libemail-utils/e-account-utils.h> #define EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), EM_TYPE_FILTER_SOURCE_ELEMENT, EMFilterSourceElementPrivate)) -typedef struct _SourceInfo { - gchar *account_name; - gchar *name; - gchar *address; - gchar *uid; -} SourceInfo; - struct _EMFilterSourceElementPrivate { EMailSession *session; - GList *sources; gchar *active_id; }; @@ -63,16 +58,6 @@ enum { }; static void -source_info_free (SourceInfo *info) -{ - g_free (info->account_name); - g_free (info->name); - g_free (info->address); - g_free (info->uid); - g_free (info); -} - -static void filter_source_element_source_changed (GtkComboBox *combo_box, EMFilterSourceElement *fs) { @@ -85,52 +70,6 @@ filter_source_element_source_changed (GtkComboBox *combo_box, } static void -filter_source_element_add_source (EMFilterSourceElement *fs, - const gchar *account_name, - const gchar *name, - const gchar *addr, - const gchar *uid) -{ - SourceInfo *info; - - g_return_if_fail (EM_IS_FILTER_SOURCE_ELEMENT (fs)); - - info = g_new0 (SourceInfo, 1); - info->account_name = g_strdup (account_name); - info->name = g_strdup (name); - info->address = g_strdup (addr); - info->uid = g_strdup (uid); - - fs->priv->sources = g_list_append (fs->priv->sources, info); -} - -static void -filter_source_element_get_sources (EMFilterSourceElement *fs) -{ - EAccountList *accounts; - const EAccount *account; - EIterator *it; - - /* should this get the global object from mail? */ - accounts = e_get_account_list (); - - for (it = e_list_get_iterator ((EList *) accounts); - e_iterator_is_valid (it); - e_iterator_next (it)) { - account = (const EAccount *) e_iterator_get (it); - - if (account->source == NULL) - continue; - - filter_source_element_add_source ( - fs, account->name, account->id->name, - account->id->address, account->uid); - } - - g_object_unref (it); -} - -static void filter_source_element_set_session (EMFilterSourceElement *element, EMailSession *session) { @@ -198,8 +137,6 @@ filter_source_element_finalize (GObject *object) priv = EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE (object); - g_list_foreach (priv->sources, (GFunc) source_info_free, NULL); - g_list_free (priv->sources); g_free (priv->active_id); /* Chain up to parent's finalize() method. */ @@ -305,7 +242,6 @@ filter_source_element_clone (EFilterElement *fe) EMFilterSourceElement *fs = (EMFilterSourceElement *) fe; EMFilterSourceElement *cpy; EMailSession *session; - GList *i; session = em_filter_source_element_get_session (fs); cpy = (EMFilterSourceElement *) em_filter_source_element_new (session); @@ -313,13 +249,6 @@ filter_source_element_clone (EFilterElement *fe) cpy->priv->active_id = g_strdup (fs->priv->active_id); - for (i = fs->priv->sources; i != NULL; i = g_list_next (i)) { - SourceInfo *info = (SourceInfo *) i->data; - filter_source_element_add_source ( - cpy, info->account_name, info->name, - info->address, info->uid); - } - return (EFilterElement *) cpy; } @@ -327,29 +256,42 @@ static GtkWidget * filter_source_element_get_widget (EFilterElement *fe) { EMFilterSourceElement *fs = (EMFilterSourceElement *) fe; + EMailSession *session; + ESourceRegistry *registry; + GList *list, *link; GtkWidget *widget; GtkComboBox *combo_box; - GList *i; - - if (fs->priv->sources == NULL) - filter_source_element_get_sources (fs); + const gchar *extension_name; widget = gtk_combo_box_text_new (); combo_box = GTK_COMBO_BOX (widget); - for (i = fs->priv->sources; i != NULL; i = g_list_next (i)) { - SourceInfo *info = (SourceInfo *) i->data; + session = em_filter_source_element_get_session (fs); + registry = e_mail_session_get_registry (session); + + 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)) { + ESource *source = E_SOURCE (link->data); + ESourceMailIdentity *extension; const gchar *display_name; const gchar *address; const gchar *name; const gchar *uid; gchar *label; - uid = info->uid; - display_name = info->account_name; + uid = e_source_get_uid (source); + display_name = e_source_get_display_name (source); - name = info->name; - address = info->address; + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + extension = e_source_get_extension (source, extension_name); + + name = e_source_mail_identity_get_name (extension); + address = e_source_mail_identity_get_address (extension); + + if (name == NULL || address == NULL) + continue; if (g_strcmp0 (display_name, address) == 0) label = g_strdup_printf ( @@ -365,6 +307,8 @@ filter_source_element_get_widget (EFilterElement *fe) g_free (label); } + g_list_free_full (list, (GDestroyNotify) g_object_unref); + if (fs->priv->active_id != NULL) { gtk_combo_box_set_active_id (combo_box, fs->priv->active_id); } else { diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index 20337c54d8..d533c47fea 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -36,10 +36,14 @@ #include <glib/gi18n.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-composition.h> +#include <libedataserver/e-source-mail-identity.h> +#include <libedataserver/e-source-mail-submission.h> + #include <e-util/e-util.h> #include <shell/e-shell.h> -#include <libemail-utils/e-account-utils.h> #include <libemail-utils/mail-mt.h> #include <libemail-engine/e-mail-folder-utils.h> @@ -605,6 +609,64 @@ em_folder_tree_model_set_session (EMFolderTreeModel *model, g_object_notify (G_OBJECT (model), "session"); } +/* Helper for em_folder_tree_model_set_folder_info() */ +static void +folder_tree_model_get_drafts_folder_uri (ESourceRegistry *registry, + CamelStore *store, + gchar **drafts_folder_uri) +{ + ESource *source; + const gchar *extension_name; + + /* In case we fail... */ + *drafts_folder_uri = NULL; + + source = em_utils_ref_mail_identity_for_store (registry, store); + if (source == NULL) + return; + + extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION; + if (e_source_has_extension (source, extension_name)) { + ESourceMailComposition *extension; + + extension = e_source_get_extension (source, extension_name); + + *drafts_folder_uri = + e_source_mail_composition_dup_drafts_folder (extension); + } + + g_object_unref (source); +} + +/* Helper for em_folder_tree_model_set_folder_info() */ +static void +folder_tree_model_get_sent_folder_uri (ESourceRegistry *registry, + CamelStore *store, + gchar **sent_folder_uri) +{ + ESource *source; + const gchar *extension_name; + + /* In case we fail... */ + *sent_folder_uri = NULL; + + source = em_utils_ref_mail_identity_for_store (registry, store); + if (source == NULL) + return; + + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + if (e_source_has_extension (source, extension_name)) { + ESourceMailSubmission *extension; + + extension = e_source_get_extension (source, extension_name); + + *sent_folder_uri = + e_source_mail_submission_dup_sent_folder (extension); + } + + g_object_unref (source); +} + void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, @@ -615,8 +677,8 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeRowReference *path_row; GtkTreeStore *tree_store; MailFolderCache *folder_cache; + ESourceRegistry *registry; EMailSession *session; - EAccount *account; guint unread; GtkTreePath *path; GtkTreeIter sub; @@ -642,10 +704,10 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, session = em_folder_tree_model_get_session (model); folder_cache = e_mail_session_get_folder_cache (session); + registry = e_mail_session_get_registry (session); uid = camel_service_get_uid (CAMEL_SERVICE (si->store)); store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); - account = e_get_account_by_uid (uid); if (!fully_loaded) load = (fi->child == NULL) && !(fi->flags & @@ -668,8 +730,8 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, unread = fi->unread; if (mail_folder_cache_get_folder_from_uri ( folder_cache, uri, &folder) && folder) { - folder_is_drafts = em_utils_folder_is_drafts (folder); - folder_is_outbox = em_utils_folder_is_outbox (folder); + folder_is_drafts = em_utils_folder_is_drafts (registry, folder); + folder_is_outbox = em_utils_folder_is_outbox (registry, folder); if (folder_is_drafts || folder_is_outbox) { gint total; @@ -712,20 +774,32 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, } } - if (account != NULL && (flags & CAMEL_FOLDER_TYPE_MASK) == 0) { - if (!folder_is_drafts && account->drafts_folder_uri != NULL) { + if ((flags & CAMEL_FOLDER_TYPE_MASK) == 0) { + gchar *drafts_folder_uri; + gchar *sent_folder_uri; + + folder_tree_model_get_drafts_folder_uri ( + registry, si->store, &drafts_folder_uri); + + folder_tree_model_get_sent_folder_uri ( + registry, si->store, &sent_folder_uri); + + if (!folder_is_drafts && drafts_folder_uri != NULL) { folder_is_drafts = e_mail_folder_uri_equal ( - CAMEL_SESSION (session), uri, - account->drafts_folder_uri); + CAMEL_SESSION (session), + uri, drafts_folder_uri); } - if (account->sent_folder_uri != NULL) { + if (sent_folder_uri != NULL) { if (e_mail_folder_uri_equal ( - CAMEL_SESSION (session), uri, - account->sent_folder_uri)) { + CAMEL_SESSION (session), + uri, sent_folder_uri)) { add_flags = CAMEL_FOLDER_TYPE_SENT; } } + + g_free (drafts_folder_uri); + g_free (sent_folder_uri); } /* Choose an icon name for the folder. */ diff --git a/mail/em-format-html.c b/mail/em-format-html.c index 0c55ecec5f..f60346dc24 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -1546,17 +1546,22 @@ efh_write_attachment (EMFormat *emf, static void efh_preparse (EMFormat *emf) { - CamelInternetAddress *addr; - EMFormatHTML *efh = EM_FORMAT_HTML (emf); + CamelInternetAddress *addr; + CamelSession *session; + ESourceRegistry *registry; if (!emf->message) { efh->priv->can_load_images = FALSE; return; } + session = em_format_get_session (emf); + registry = e_mail_session_get_registry (E_MAIL_SESSION (session)); + addr = camel_mime_message_get_from (emf->message); - efh->priv->can_load_images = em_utils_in_addressbook (addr, FALSE); + efh->priv->can_load_images = em_utils_in_addressbook ( + registry, addr, FALSE); } static void @@ -2678,6 +2683,8 @@ efh_format_full_headers (EMFormatHTML *efh, gboolean have_icon = FALSE; const gchar *photo_name = NULL; CamelInternetAddress *cia = NULL; + CamelSession *session; + ESourceRegistry *registry; gboolean face_decoded = FALSE, contact_has_photo = FALSE; guchar *face_header_value = NULL; gsize face_header_len = 0; @@ -2689,6 +2696,9 @@ efh_format_full_headers (EMFormatHTML *efh, if (cancellable && g_cancellable_is_cancelled (cancellable)) return; + session = em_format_get_session (emf); + registry = e_mail_session_get_registry (E_MAIL_SESSION (session)); + ct = camel_mime_part_get_content_type ((CamelMimePart *) part); charset = camel_content_type_param (ct, "charset"); charset = camel_iconv_charset_name (charset); @@ -2871,7 +2881,8 @@ efh_format_full_headers (EMFormatHTML *efh, camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name); only_local_photo = em_format_html_get_only_local_photos (efh); - photopart = em_utils_contact_photo (cia, only_local_photo); + photopart = em_utils_contact_photo ( + registry, cia, only_local_photo); if (photopart) { g_string_append (buffer, "<td align=\"right\" valign=\"top\">"); diff --git a/mail/em-subscription-editor.c b/mail/em-subscription-editor.c index f695a88d87..8221115c46 100644 --- a/mail/em-subscription-editor.c +++ b/mail/em-subscription-editor.c @@ -25,7 +25,6 @@ #include <string.h> #include <glib/gi18n-lib.h> -#include <libemail-utils/e-account-utils.h> #include <libemail-utils/mail-mt.h> #include <libemail-engine/mail-tools.h> #include <libemail-engine/mail-ops.h> @@ -1555,19 +1554,24 @@ subscription_editor_constructed (GObject *object) /* Pick an initial store based on the default mail account, if * one wasn't already given in em_subscription_editor_new(). */ if (editor->priv->initial_store == NULL) { - EAccount *account; + ESource *source; + ESourceRegistry *registry; CamelService *service; EMailSession *session; - account = e_get_default_account (); - session = em_subscription_editor_get_session (editor); + registry = e_mail_session_get_registry (session); + + source = e_source_registry_ref_default_mail_account (registry); service = camel_session_get_service ( - CAMEL_SESSION (session), account->uid); + CAMEL_SESSION (session), + e_source_get_uid (source)); if (CAMEL_IS_SUBSCRIBABLE (service)) editor->priv->initial_store = g_object_ref (service); + + g_object_unref (source); } /* Chain up to parent's constructed() method. */ diff --git a/mail/em-utils.c b/mail/em-utils.c index 8a6383d755..11dc1217c7 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -52,6 +52,15 @@ #include <libedataserver/e-data-server-util.h> #include <libedataserver/e-flag.h> #include <libedataserver/e-proxy.h> +#include <libedataserver/e-source-address-book.h> +#include <libedataserver/e-source-autocomplete.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-composition.h> +#include <libedataserver/e-source-mail-identity.h> +#include <libedataserver/e-source-mail-submission.h> +#include <libedataserver/e-data-server-util.h> +#include <libedataserver/e-flag.h> +#include <libedataserver/e-proxy.h> #include <e-util/e-util.h> #include <e-util/e-util-private.h> @@ -62,7 +71,6 @@ #include <shell/e-shell.h> #include <widgets/misc/e-attachment.h> -#include <libemail-utils/e-account-utils.h> #include <libemail-utils/mail-mt.h> #include <libemail-engine/e-mail-folder-utils.h> @@ -1266,10 +1274,13 @@ void em_utils_empty_trash (GtkWidget *parent, EMailSession *session) { + ESourceRegistry *registry; GList *list, *link; g_return_if_fail (E_IS_MAIL_SESSION (session)); + registry = e_mail_session_get_registry (session); + if (!em_utils_prompt_user ((GtkWindow *) parent, "prompt-on-empty-trash", "mail:ask-empty-trash", NULL)) @@ -1278,10 +1289,11 @@ em_utils_empty_trash (GtkWidget *parent, list = camel_session_list_services (CAMEL_SESSION (session)); for (link = list; link != NULL; link = g_list_next (link)) { - EAccount *account; CamelProvider *provider; CamelService *service; + ESource *source; const gchar *uid; + gboolean enabled = TRUE; service = CAMEL_SERVICE (link->data); provider = camel_service_get_provider (service); @@ -1293,16 +1305,15 @@ em_utils_empty_trash (GtkWidget *parent, if ((provider->flags & CAMEL_PROVIDER_IS_STORAGE) == 0) continue; - account = e_get_account_by_uid (uid); + source = e_source_registry_ref_source (registry, uid); - /* The local store has no corresponding - * EAccount, so skip the enabled check. */ - if (account != NULL) { - if (!account->enabled) - continue; + if (source != NULL) { + enabled = e_source_get_enabled (source); + g_object_unref (source); } - mail_empty_trash (CAMEL_STORE (service)); + if (enabled) + mail_empty_trash (CAMEL_STORE (service)); } g_list_free (list); @@ -1310,29 +1321,6 @@ em_utils_empty_trash (GtkWidget *parent, /* ********************************************************************** */ -void -em_utils_clear_get_password_canceled_accounts_flag (void) -{ - EAccountList *account_list; - EIterator *iterator; - - account_list = e_get_account_list (); - - for (iterator = e_list_get_iterator (E_LIST (account_list)); - e_iterator_is_valid (iterator); - e_iterator_next (iterator)) { - EAccount *account = (EAccount *) e_iterator_get (iterator); - - if (account && account->source) - account->source->get_password_canceled = FALSE; - - if (account && account->transport) - account->transport->get_password_canceled = FALSE; - } - - g_object_unref (iterator); -} - gchar * em_utils_url_unescape_amp (const gchar *url) { diff --git a/mail/em-utils.h b/mail/em-utils.h index bce64eebc3..303f0efddd 100644 --- a/mail/em-utils.h +++ b/mail/em-utils.h @@ -27,7 +27,6 @@ #include <sys/types.h> #include <camel/camel.h> #include <libedataserver/e-proxy.h> -#include <libedataserver/e-account.h> #include <libemail-engine/e-mail-session.h> #include <libemail-engine/e-mail-utils.h> @@ -73,14 +72,9 @@ gchar *em_utils_message_to_html (CamelSession *session, CamelMimeMessage *msg, c void em_utils_empty_trash (GtkWidget *parent, EMailSession *session); -/* clears flag 'get_password_canceled' at every known accounts, so if needed, get_password will show dialog */ -void em_utils_clear_get_password_canceled_accounts_flag (void); - /* Unescapes & back to a real & in URIs */ gchar *em_utils_url_unescape_amp (const gchar *url); -void emu_free_mail_account_sort_order_cache (void); - void emu_restore_folder_tree_state (EMFolderTree *folder_tree); gboolean em_utils_is_re_in_subject (struct _EShell *shell, diff --git a/mail/mail-config.ui b/mail/mail-config.ui index 0d906ed6df..224f659487 100644 --- a/mail/mail-config.ui +++ b/mail/mail-config.ui @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <interface> - <!-- interface-requires evolution 0.0 --> <requires lib="gtk+" version="2.16"/> <object class="GtkDialog" id="add-custom-junk-header"> <property name="width_request">400</property> @@ -143,244 +142,6 @@ <action-widget response="-3">junk-header-ok</action-widget> </action-widgets> </object> - <object class="GtkDialog" id="add_script_signature"> - <property name="can_focus">False</property> - <property name="type_hint">normal</property> - <child internal-child="vbox"> - <object class="GtkBox" id="dialog-vbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">12</property> - <child internal-child="action_area"> - <object class="GtkButtonBox" id="dialog-action_area1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="layout_style">end</property> - <child> - <object class="GtkButton" id="button_add_script_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <child> - <object class="GtkAlignment" id="alignment30"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkHBox" id="hbox221"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child> - <object class="GtkImage" id="image5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-add</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label547"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Add Signature</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_add_script_cancel"> - <property name="label">gtk-cancel</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="pack_type">end</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="vbox160"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkVBox" id="vbox_add_script_signature"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="spacing">6</property> - <child> - <object class="GtkHBox" id="hboxImageAndHelp"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkImage" id="pixmap1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="yalign">0</property> - <property name="stock">gtk-dialog-info</property> - <property name="icon-size">6</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label456"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">The output of this script will be used as your -signature. The name you specify will be used -for display purposes only. </property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkTable" id="tblNameScript"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="column_spacing">6</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="label459"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">_Name:</property> - <property name="use_underline">True</property> - <property name="justify">center</property> - <property name="mnemonic_widget">entry_add_script_name</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label460"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">_Script:</property> - <property name="use_underline">True</property> - <property name="justify">center</property> - <property name="mnemonic_widget">filechooserbutton_add_script</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="entry_add_script_name"> - <property name="visible">True</property> - <property name="can_focus">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkFileChooserButton" id="filechooserbutton_add_script"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="title" translatable="yes"></property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - <action-widgets> - <action-widget response="0">button_add_script_add</action-widget> - <action-widget response="0">button_add_script_cancel</action-widget> - </action-widgets> - </object> <object class="GtkAdjustment" id="adjustment1"> <property name="upper">10</property> <property name="value">1.5</property> @@ -845,56 +606,6 @@ for display purposes only. </property> <property name="position">0</property> </packing> </child> - <child> - <object class="GtkVBox" id="signature-preview-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="signature-preview-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Preview</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="signature-preview-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkScrolledWindow" id="signature-preview-scrolled-window"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">in</property> - <child> - <placeholder/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> </object> <packing> <property name="position">1</property> @@ -1706,18 +1417,6 @@ for display purposes only. </property> <property name="y_options"></property> </packing> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> <packing> <property name="expand">False</property> @@ -3287,6 +2986,19 @@ for display purposes only. </property> </packing> </child> </object> + <object class="GtkSizeGroup" id="composer-combo-box-size-group"> + <widgets> + <widget name="comboboxReplyStyle"/> + <widget name="comboboxForwardStyle"/> + </widgets> + </object> + <object class="GtkSizeGroup" id="composer-label-size-group"> + <widgets> + <widget name="lblCharset"/> + <widget name="lblReplyStyle"/> + <widget name="lblForwardStyle"/> + </widgets> + </object> <object class="GtkListStore" id="use_ssl_model"> <columns> <!-- column-name Label --> @@ -3309,2864 +3021,4 @@ for display purposes only. </property> </row> </data> </object> - <object class="GtkVBox" id="vboxFoldersBorder"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="spacing">12</property> - <child> - <object class="GtkVBox" id="special-folders-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="special-folders-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Special Folders</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="special-folders-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="xscale">0</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="special-folders-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">5</property> - <property name="n_columns">2</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="drafts_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Drafts _Folder:</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="sent_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Sent _Messages Folder:</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="trash_folder_check"> - <property name="label" translatable="yes">_Trash Folder:</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="junk_folder_check"> - <property name="label" translatable="yes">_Junk Folder:</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="revert-button-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="xscale">0</property> - <child> - <object class="GtkButton" id="default_folders_button"> - <property name="label">gtk-revert-to-saved</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <property name="use_stock">True</property> - </object> - </child> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="EMFolderSelectionButton" id="drafts_button"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="EMFolderSelectionButton" id="sent_button"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="EMFolderSelectionButton" id="trash_folder_butt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="EMFolderSelectionButton" id="junk_folder_butt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="composing-messages-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="composing-messages-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Composing Messages</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="composing-messages-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="composing-messages-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">4</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkAlignment" id="always-bcc-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">18</property> - <child> - <object class="GtkEntry" id="bcc_addrs"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - </child> - </object> - <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="always_bcc"> - <property name="label" translatable="yes">Always _blind carbon-copy (bcc) to:</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="always-cc-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">18</property> - <child> - <object class="GtkEntry" id="cc_addrs"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - </child> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="always_cc"> - <property name="label" translatable="yes">Alway_s carbon-copy (cc) to:</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="y_options"></property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="message-receipts-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="message-receipts-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Message Receipts</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="message-receipts-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkHBox" id="message-receipts-hbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="label583"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">S_end message receipts:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">receipt_policy_dropdown</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="receipt_policy_dropdown"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - </object> - <object class="GtkVBox" id="vboxIdentityBorder"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="spacing">12</property> - <child> - <object class="GtkVBox" id="management-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="management-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Account Information</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="management-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="management-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="column_spacing">6</property> - <property name="row_spacing">2</property> - <child> - <object class="GtkVBox" id="account_vbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="management_description_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Type the name by which you would like to refer to this account. -For example: "Work" or "Personal"</property> - <property name="use_markup">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hboxIdentityName"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="management_name_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Name:</property> - <property name="use_underline">True</property> - <property name="justify">right</property> - <property name="mnemonic_widget">management_name</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="management_name"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="identity-required-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="identity-required-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Required Information</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="identity-required-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="identity-required-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkEntry" id="identity_address"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - <accessibility> - <relation type="labelled-by" target="identity_address_label"/> - <relation type="labelled-by" target="identity-required-header"/> - </accessibility> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="identity_address_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Email _Address:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">identity_address</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="identity_full_name_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Full Nam_e:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">identity_full_name</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="identity_full_name"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - <accessibility> - <relation type="labelled-by" target="identity-required-header"/> - <relation type="labelled-by" target="identity_full_name_label"/> - </accessibility> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="identity-optional-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="identity-optional-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Optional Information</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="identity-optional-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="identity-optional-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">4</property> - <property name="n_columns">2</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="sigLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Signat_ure:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">signature_dropdown</property> - </object> - <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox169"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkComboBox" id="signature_dropdown"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="sigAddNew"> - <property name="label" translatable="yes">Add Ne_w Signature...</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <signal name="clicked" handler="sigAddNewClicked" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="pack_type">end</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="identity_organization"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - <accessibility> - <relation type="labelled-by" target="identity_organization_label"/> - <relation type="labelled-by" target="identity-optional-header"/> - </accessibility> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="identity_organization_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Or_ganization:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">identity_organization</property> - </object> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="identity_reply_to"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - <accessibility> - <relation type="labelled-by" target="identity-optional-header"/> - <relation type="labelled-by" target="reply_to_label"/> - </accessibility> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="reply_to_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Re_ply-To:</property> - <property name="use_underline">True</property> - <property name="justify">center</property> - <property name="mnemonic_widget">identity_reply_to</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="management_default"> - <property name="label" translatable="yes">_Make this my default account</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="right_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - </object> - <object class="GtkVBox" id="vboxSecurityBorder"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="spacing">12</property> - <child> - <object class="GtkVBox" id="security-general-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="security-general-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">General</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="security-general-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkCheckButton" id="pgp_no_imip_sign"> - <property name="label" translatable="yes">_Do not sign meeting requests (for Outlook compatibility)</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="pgp-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="pgp-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Pretty Good Privacy (PGP/GPG)</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="pgp-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="pgp-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="column_spacing">6</property> - <property name="row_spacing">2</property> - <child> - <object class="GtkVBox" id="vboxPGP"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkHBox" id="hbox63"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="pgp_key_id_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">PGP/GPG _Key ID:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">pgp_key</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="pgp_key"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="pgp_hash_algo_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Si_gning algorithm:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">pgp_hash_algo</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="pgp_hash_algo"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="model">hash_algo_model</property> - <child> - <object class="GtkCellRendererText" id="pgp_hash_algo_renderer"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="pgp_always_sign"> - <property name="label" translatable="yes">Al_ways sign outgoing messages when using this account</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="pgp_encrypt_to_self"> - <property name="label" translatable="yes">Always encrypt to _myself when sending encrypted messages</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="pgp_always_trust"> - <property name="label" translatable="yes">Always _trust keys in my keyring when encrypting</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">4</property> - </packing> - </child> - </object> - <packing> - <property name="y_options"></property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="smime-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="smime-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Secure MIME (S/MIME)</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="smime-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="smime_table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">7</property> - <property name="n_columns">3</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkEntry" id="smime_sign_key"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="smime_encrypt_key"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="smime_encrypt_to_self"> - <property name="label" translatable="yes">Also encrypt to sel_f when sending encrypted messages</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="smime_encrypt_default"> - <property name="label" translatable="yes">Encrypt out_going messages (by default)</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="smime_sign_default"> - <property name="label" translatable="yes">Digitally sign o_utgoing messages (by default)</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="right_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkHSeparator" id="hseparator1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - <property name="y_padding">6</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Encry_ption certificate:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">smime_encrypt_key</property> - </object> - <packing> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label469"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Sig_ning certificate:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">smime_sign_key</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox208"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkButton" id="smime_encrypt_key_select"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <child> - <object class="GtkAlignment" id="alignment28"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkHBox" id="hbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child> - <object class="GtkImage" id="image3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-open</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="button98"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">S_elect...</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="smime_encrypt_key_clear"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <child> - <object class="GtkAlignment" id="alignment35"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkHBox" id="hbox230"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child> - <object class="GtkImage" id="image10"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-clear</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label577"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Clea_r</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="smime_hash_algo_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Signing _algorithm:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">smime_hash_algo</property> - </object> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="smime_hash_algo_alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="xscale">0</property> - <child> - <object class="GtkComboBox" id="smime_hash_algo"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="model">hash_algo_model</property> - <child> - <object class="GtkCellRendererText" id="smime_hash_algo_renderer"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - </child> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="yalign">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkHBox" id="hbox209"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkButton" id="smime_sign_key_select"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <child> - <object class="GtkAlignment" id="alignment29"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkHBox" id="hbox2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child> - <object class="GtkImage" id="image4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-open</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Select...</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="smime_sign_key_clear"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <child> - <object class="GtkAlignment" id="alignment34"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkHBox" id="hbox229"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child> - <object class="GtkImage" id="image9"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-clear</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label576"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Cle_ar</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - </object> - <object class="GtkVBox" id="vboxSourceBorder"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="spacing">12</property> - <child> - <object class="GtkTable" id="source-type-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">2</property> - <property name="n_columns">3</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="source_type_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Server _Type:</property> - <property name="use_underline">True</property> - <property name="justify">right</property> - <property name="mnemonic_widget">source_type_dropdown</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label442"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="label" translatable="yes">Description:</property> - <property name="justify">center</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="source_description"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="label" translatable="yes">description</property> - <property name="wrap">True</property> - <property name="width-chars">40</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkComboBoxText" id="source_type_dropdown"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHSeparator" id="source-separator"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="source-config-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="source-config-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Configuration</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="source-config-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="source-config-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">3</property> - <property name="n_columns">4</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="source_host_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">_Server:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">source_host</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="source_port_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">1</property> - <property name="label">_Port:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">source_port</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="source_user_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">User_name:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">source_user</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="source_host"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="EPortEntry" id="source_port" type-func="e_port_entry_get_type"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="has_entry">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="x_options"></property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="source_user"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">4</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="source_path_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">_Path:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">source_path_entry</property> - </object> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkFileChooserButton" id="source_path_entry"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="title" translatable="yes">Mailbox location</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="source-security-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="source-security-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Security</property> - <property name="mnemonic_widget">source_auth_dropdown</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="source-security-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkVBox" id="source-security-vbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkHBox" id="source_ssl_hbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="lblSourceUseSSL"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Use secure connection:</property> - <property name="use_underline">True</property> - <property name="justify">center</property> - <property name="mnemonic_widget">source_use_ssl</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="source_use_ssl"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="model">use_ssl_model</property> - <property name="id_column">1</property> - <child> - <object class="GtkCellRendererText" id="source_use_ssl_renderer"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="source_ssl_disabled"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-dialog-warning</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label514"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">SSL is not supported in this build of Evolution</property> - <property name="justify">center</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="source-auth-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="source-auth-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">_Authentication Type</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">source_auth_dropdown</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="source-auth-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkVBox" id="source-auth-vbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkHBox" id="hbox199"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="EAuthComboBox" id="source_auth_dropdown" type-func="e_auth_combo_box_get_type"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="source_check_supported"> - <property name="label" translatable="yes">Ch_eck for Supported Types</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="source_remember_password"> - <property name="label" translatable="yes">Re_member password</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">4</property> - </packing> - </child> - </object> - <object class="GtkVBox" id="vboxTransportBorder"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="spacing">12</property> - <child> - <object class="GtkTable" id="transport-type-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">2</property> - <property name="n_columns">3</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="transport_type_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="label" translatable="yes">Server _Type:</property> - <property name="use_underline">True</property> - <property name="justify">right</property> - <property name="mnemonic_widget">transport_type_dropdown</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label50"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="label" translatable="yes">Description:</property> - <property name="justify">right</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkComboBoxText" id="transport_type_dropdown"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="transport_description"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="label" translatable="yes">description</property> - <property name="wrap">True</property> - <property name="width-chars">40</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHSeparator" id="transport-separator"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="transport-server-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="transport-server-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Server Configuration</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="transport-server-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="transport-server-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">2</property> - <property name="n_columns">4</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="transport_host_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">_Server:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">transport_host</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="transport_port_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Port:</property> - <property name="use_underline">True</property> - <property name="justify">right</property> - <property name="mnemonic_widget">transport_port</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="transport_host"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="EPortEntry" id="transport_port" type-func="e_port_entry_get_type"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="has_entry">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="x_options"></property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="transport_needs_auth"> - <property name="label" translatable="yes">Ser_ver requires authentication</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="transport-security-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="transport-security-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Security</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="transport-security-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="transport-security-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">2</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkHBox" id="transport_ssl_disabled"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-dialog-warning</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="transport_ssl_disabled_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">SSL is not supported in this build of Evolution</property> - <property name="justify">center</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkHBox" id="transport_ssl_hbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="lblTransportUseSSL"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Use secure connection:</property> - <property name="use_underline">True</property> - <property name="justify">center</property> - <property name="mnemonic_widget">transport_use_ssl</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="transport_use_ssl"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="model">use_ssl_model</property> - <property name="id_column">1</property> - <child> - <object class="GtkCellRendererText" id="transport_use_ssl_renderer"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="y_options"></property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkVBox" id="transport-auth-section"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="transport-auth-header"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Authentication</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="transport-auth-alignment"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkTable" id="transport-auth-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">3</property> - <property name="n_columns">2</property> - <property name="column_spacing">12</property> - <property name="row_spacing">6</property> - <child> - <object class="GtkLabel" id="transport_auth_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">T_ype:</property> - <property name="use_underline">True</property> - <property name="justify">center</property> - <property name="mnemonic_widget">transport_auth_dropdown</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="transport_user_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">User _Name:</property> - <property name="use_underline">True</property> - <property name="justify">right</property> - <property name="mnemonic_widget">transport_user</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkEntry" id="transport_user"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="transport_remember_password"> - <property name="label" translatable="yes">Remember _password</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="xscale">0</property> - <child> - <object class="GtkHBox" id="hbox195"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="EAuthComboBox" id="transport_auth_dropdown" type-func="e_auth_combo_box_get_type"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="transport_check_supported"> - <property name="label" translatable="yes">Ch_eck for Supported Types</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">4</property> - </packing> - </child> - </object> - <object class="GtkSizeGroup" id="composer-combo-box-size-group"> - <widgets> - <widget name="comboboxReplyStyle"/> - <widget name="comboboxForwardStyle"/> - </widgets> - </object> - <object class="GtkSizeGroup" id="composer-label-size-group"> - <widgets> - <widget name="lblCharset"/> - <widget name="lblReplyStyle"/> - <widget name="lblForwardStyle"/> - </widgets> - </object> - <object class="GtkVBox" id="vboxReviewBorder"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkTable" id="personal-details-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">3</property> - <property name="n_columns">2</property> - <property name="row_spacing">4</property> - <property name="column_spacing">8</property> - <child> - <object class="GtkLabel" id="personal-details-label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Personal Details:</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="personal-name-label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Name:</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="personal-name-entry"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="personal-email-label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Email address:</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="personal-email-entry"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkTable" id="server-details-table"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">5</property> - <property name="n_columns">3</property> - <property name="row_spacing">4</property> - <property name="column_spacing">8</property> - <child> - <object class="GtkLabel" id="details-label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Details:</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="details-label-receiving"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Receiving</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="details-label-sending"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Sending</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="details-server-type"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Server type:</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="details-server-address"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Server address:</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="details-user-name"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Username:</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">3</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="details-encryption"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Encryption:</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">4</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="receive_server_type"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">none</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="send_server_type"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">none</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="receive_server_address"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">none</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="send_server_address"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">none</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="receive_username"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">3</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="send_username"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">3</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="receive_encryption"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">4</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="send_encryption"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">label</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">4</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - </object> </interface> diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index ee3cd164e7..d68b928124 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -29,12 +29,12 @@ #include <glib/gi18n.h> -#include <libedataserver/e-account-list.h> +#include <libedataserver/e-source-mail-account.h> +#include <libedataserver/e-source-mail-submission.h> #include <shell/e-shell.h> #include <e-util/e-util.h> -#include <libemail-utils/e-account-utils.h> #include <libemail-utils/mail-mt.h> /* This is our hack, not part of libcamel. */ @@ -490,7 +490,7 @@ static struct _send_data * build_dialog (GtkWindow *parent, EMailSession *session, CamelFolder *outbox, - EAccount *outgoing_account, + CamelService *transport, gboolean allow_send) { GtkDialog *gd; @@ -508,7 +508,6 @@ build_dialog (GtkWindow *parent, GtkWidget *progress_bar; GtkWidget *cancel_button; EMailAccountStore *account_store; - CamelService *transport = NULL; struct _send_info *info; gchar *pretty_url; EMEventTargetSendReceive *target; @@ -516,17 +515,6 @@ build_dialog (GtkWindow *parent, account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session)); - /* Convert the outgoing account to a CamelTransport. */ - if (outgoing_account != NULL) { - gchar *transport_uid; - - transport_uid = g_strdup_printf ( - "%s-transport", outgoing_account->uid); - transport = camel_session_get_service ( - CAMEL_SESSION (session), transport_uid); - g_free (transport_uid); - } - send_recv_dialog = gtk_dialog_new (); gd = GTK_DIALOG (send_recv_dialog); @@ -1124,14 +1112,57 @@ receive_update_got_store (CamelStore *store, } } +static CamelService * +get_default_transport (EMailSession *session) +{ + ESource *source; + ESourceRegistry *registry; + CamelService *service; + const gchar *extension_name; + const gchar *uid; + + registry = e_mail_session_get_registry (session); + source = e_source_registry_ref_default_mail_identity (registry); + + if (source == NULL) + return NULL; + + extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; + if (e_source_has_extension (source, extension_name)) { + ESourceMailSubmission *extension; + gchar *uid; + + extension = e_source_get_extension (source, extension_name); + uid = e_source_mail_submission_dup_transport_uid (extension); + + g_object_unref (source); + source = e_source_registry_ref_source (registry, uid); + + g_free (uid); + } else { + g_object_unref (source); + source = NULL; + } + + if (source == NULL) + return NULL; + + uid = e_source_get_uid (source); + service = camel_session_get_service (CAMEL_SESSION (session), uid); + + g_object_unref (source); + + return service; +} + static GtkWidget * send_receive (GtkWindow *parent, EMailSession *session, gboolean allow_send) { CamelFolder *local_outbox; + CamelService *transport; struct _send_data *data; - EAccount *account; GList *scan; if (send_recv_dialog != NULL) { @@ -1144,16 +1175,14 @@ send_receive (GtkWindow *parent, if (!camel_session_get_online (CAMEL_SESSION (session))) return send_recv_dialog; - account = e_get_default_account (); - if (!account || !account->transport->url) - return send_recv_dialog; + transport = get_default_transport (session); local_outbox = e_mail_session_get_local_folder ( session, E_MAIL_LOCAL_FOLDER_OUTBOX); data = build_dialog ( - parent, session, local_outbox, account, allow_send); + parent, session, local_outbox, transport, allow_send); for (scan = data->infos; scan != NULL; scan = scan->next) { struct _send_info *info = scan->data; @@ -1165,7 +1194,7 @@ send_receive (GtkWindow *parent, case SEND_RECEIVE: mail_fetch_mail ( CAMEL_STORE (info->service), - info->keep_on_server, 0, -1, + CAMEL_FETCH_OLD_MESSAGES, -1, E_FILTER_SOURCE_INCOMING, NULL, NULL, NULL, info->cancellable, @@ -1210,201 +1239,6 @@ mail_receive (GtkWindow *parent, return send_receive (parent, session, FALSE); } -struct _auto_data { - EAccount *account; - EMailSession *session; - gint period; /* in seconds */ - gint timeout_id; -}; - -static GHashTable *auto_active; - -static gboolean -auto_timeout (gpointer data) -{ - CamelService *service; - CamelSession *session; - struct _auto_data *info = data; - - session = CAMEL_SESSION (info->session); - - service = camel_session_get_service ( - session, info->account->uid); - g_return_val_if_fail (CAMEL_IS_SERVICE (service), TRUE); - - if (camel_session_get_online (session)) - mail_receive_service (service); - - return TRUE; -} - -static void -auto_account_removed (EAccountList *eal, - EAccount *ea, - gpointer dummy) -{ - struct _auto_data *info = g_object_get_data((GObject *)ea, "mail-autoreceive"); - - g_return_if_fail (info != NULL); - - if (info->timeout_id) { - g_source_remove (info->timeout_id); - info->timeout_id = 0; - } -} - -static void -auto_account_finalized (struct _auto_data *info) -{ - if (info->session != NULL) - g_object_unref (info->session); - if (info->timeout_id) - g_source_remove (info->timeout_id); - g_free (info); -} - -static void -auto_account_commit (struct _auto_data *info) -{ - gint period, check; - - check = info->account->enabled - && e_account_get_bool (info->account, E_ACCOUNT_SOURCE_AUTO_CHECK) - && e_account_get_string (info->account, E_ACCOUNT_SOURCE_URL); - period = e_account_get_int (info->account, E_ACCOUNT_SOURCE_AUTO_CHECK_TIME) * 60; - period = MAX (60, period); - - if (info->timeout_id - && (!check - || period != info->period)) { - g_source_remove (info->timeout_id); - info->timeout_id = 0; - } - info->period = period; - if (check && info->timeout_id == 0) - info->timeout_id = g_timeout_add_seconds (info->period, auto_timeout, info); -} - -static void -auto_account_added (EAccountList *eal, - EAccount *ea, - EMailSession *session) -{ - struct _auto_data *info; - - info = g_malloc0 (sizeof (*info)); - info->account = ea; - info->session = g_object_ref (session); - g_object_set_data_full ( - G_OBJECT (ea), "mail-autoreceive", info, - (GDestroyNotify) auto_account_finalized); - auto_account_commit (info); -} - -static void -auto_account_changed (EAccountList *eal, - EAccount *ea, - gpointer dummy) -{ - struct _auto_data *info; - - info = g_object_get_data (G_OBJECT (ea), "mail-autoreceive"); - - if (info != NULL) - auto_account_commit (info); -} - -static void -auto_online (EShell *shell) -{ - EIterator *iter; - EAccountList *accounts; - EShellSettings *shell_settings; - struct _auto_data *info; - gboolean can_update_all; - - if (!e_shell_get_online (shell)) - return; - - shell_settings = e_shell_get_shell_settings (shell); - - can_update_all = - e_shell_settings_get_boolean ( - shell_settings, "mail-check-on-start") && - e_shell_settings_get_boolean ( - shell_settings, "mail-check-all-on-start"); - - accounts = e_get_account_list (); - for (iter = e_list_get_iterator ((EList *) accounts); - e_iterator_is_valid (iter); - e_iterator_next (iter)) { - EAccount *account = (EAccount *) e_iterator_get (iter); - - if (!account || !account->enabled) - continue; - - info = g_object_get_data ( - G_OBJECT (account), "mail-autoreceive"); - if (info && (info->timeout_id || can_update_all)) - auto_timeout (info); - } - - if (iter) - g_object_unref (iter); -} - -/* call to setup initial, and after changes are made to the config */ -/* FIXME: Need a cleanup funciton for when object is deactivated */ -void -mail_autoreceive_init (EMailSession *session) -{ - EShell *shell; - EShellSettings *shell_settings; - EAccountList *accounts; - EIterator *iter; - - g_return_if_fail (E_IS_MAIL_SESSION (session)); - - if (auto_active) - return; - - accounts = e_get_account_list (); - auto_active = g_hash_table_new (g_str_hash, g_str_equal); - - g_signal_connect ( - accounts, "account-added", - G_CALLBACK (auto_account_added), session); - g_signal_connect ( - accounts, "account-removed", - G_CALLBACK (auto_account_removed), NULL); - g_signal_connect ( - accounts, "account-changed", - G_CALLBACK (auto_account_changed), NULL); - - for (iter = e_list_get_iterator ((EList *) accounts); - e_iterator_is_valid (iter); - e_iterator_next (iter)) - auto_account_added ( - accounts, (EAccount *) - e_iterator_get (iter), session); - - shell = e_shell_get_default (); - shell_settings = e_shell_get_shell_settings (shell); - - if (e_shell_settings_get_boolean ( - shell_settings, "mail-check-on-start")) { - auto_online (shell); - - /* also flush outbox on start */ - if (e_shell_get_online (shell)) - mail_send (session); - } - - g_signal_connect ( - shell, "notify::online", - G_CALLBACK (auto_online), NULL); -} - /* We setup the download info's in a hashtable, if we later * need to build the gui, we insert them in to add them. */ void @@ -1458,7 +1292,7 @@ mail_receive_service (CamelService *service) case SEND_RECEIVE: mail_fetch_mail ( CAMEL_STORE (service), - info->keep_on_server, 0, -1, + CAMEL_FETCH_OLD_MESSAGES, -1, E_FILTER_SOURCE_INCOMING, NULL, NULL, NULL, info->cancellable, @@ -1495,16 +1329,14 @@ mail_send (EMailSession *session) { CamelFolder *local_outbox; CamelService *service; - EAccount *account; struct _send_info *info; struct _send_data *data; send_info_t type = SEND_INVALID; - gchar *transport_uid; g_return_if_fail (E_IS_MAIL_SESSION (session)); - account = e_get_default_transport (); - if (account == NULL || account->transport->url == NULL) + service = get_default_transport (session); + if (service == NULL) return; data = setup_send_data (session); @@ -1515,24 +1347,12 @@ mail_send (EMailSession *session) return; } - transport_uid = g_strconcat (account->uid, "-transport", NULL); - - service = camel_session_get_service ( - CAMEL_SESSION (session), transport_uid); - - if (!CAMEL_IS_TRANSPORT (service)) { - g_free (transport_uid); - return; - } - d(printf("starting non-interactive send of '%s'\n", transport->url)); type = get_receive_type (service); - if (type == SEND_INVALID) { - g_free (transport_uid); + if (type == SEND_INVALID) return; - } info = g_malloc0 (sizeof (*info)); info->type = SEND_SEND; @@ -1556,10 +1376,6 @@ mail_send (EMailSession *session) e_mail_session_get_local_folder ( session, E_MAIL_LOCAL_FOLDER_OUTBOX); - g_free (transport_uid); - - g_return_if_fail (CAMEL_IS_TRANSPORT (service)); - mail_send_queue ( session, local_outbox, CAMEL_TRANSPORT (service), diff --git a/mail/mail.error.xml b/mail/mail.error.xml index c996362a22..65cf052db6 100644 --- a/mail/mail.error.xml +++ b/mail/mail.error.xml @@ -300,24 +300,6 @@ all proxy information will be deleted permanently.</_secondary> <button _label="_Disable" response="GTK_RESPONSE_YES"/> </error> - <error id="no-save-signature" type="error"> - <_primary>Could not save signature file.</_primary> - <secondary xml:space="preserve">{0}.</secondary> - </error> - - <error id="signature-notscript" type="error"> - <_primary>Cannot set signature script "{0}".</_primary> - <_secondary xml:space="preserve">The script file must exist and be executable.</_secondary> - </error> - - <error id="ask-signature-changed" type="question" default="GTK_RESPONSE_YES"> - <_primary>Do you wish to save your changes?</_primary> - <_secondary xml:space="preserve">This signature has been changed, but has not been saved.</_secondary> - <button _label="_Discard changes" response="GTK_RESPONSE_NO"/> - <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/> - <button stock="gtk-save" response="GTK_RESPONSE_YES"/> - </error> - <error id="vfolder-notexist" type="error"> <_primary>Cannot edit Search Folder "{0}" as it does not exist.</_primary> <_secondary xml:space="preserve">This folder may have been added implicitly, @@ -444,16 +426,6 @@ An mbox account will be created to preserve the old mbox folders. You can delete <button _label="N_ever" response="GTK_RESPONSE_CANCEL"/> </error> - <error id="signature-already-exists" type="error" modal="true"> - <_primary>Signature Already Exists</_primary> - <_secondary>A signature already exists with the name "{0}". Please specify a different name. </_secondary> - </error> - - <error id="blank-signature" type="error" modal="true"> - <_primary>Blank Signature</_primary> - <_secondary>Please provide an unique name to identify this signature.</_secondary> - </error> - <error id="send-no-account-enabled" type="warning"> <_primary>This message cannot be sent because the account you chose to send with is not enabled</_primary> <_secondary xml:space="preserve">Please enable the account or send using another account.</_secondary> diff --git a/mail/test-mail-autoconfig.c b/mail/test-mail-autoconfig.c new file mode 100644 index 0000000000..10977a17b2 --- /dev/null +++ b/mail/test-mail-autoconfig.c @@ -0,0 +1,53 @@ +/* + * test-mail-autoconfig.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 <stdlib.h> + +#include "e-mail-autoconfig.h" + +gint +main (gint argc, + gchar **argv) +{ + EMailAutoconfig *autoconfig; + GError *error = NULL; + + g_type_init (); + + if (argc < 2) { + g_printerr ("USAGE: %s EMAIL-ADDRESS\n", argv[0]); + exit (EXIT_FAILURE); + } + + autoconfig = e_mail_autoconfig_new_sync (argv[1], NULL, &error); + + if (error != NULL) { + g_warn_if_fail (autoconfig == NULL); + g_printerr ("%s\n", error->message); + g_error_free (error); + exit (EXIT_FAILURE); + } + + g_assert (E_IS_MAIL_AUTOCONFIG (autoconfig)); + + g_print ("%s\n", e_mail_autoconfig_get_markup_content (autoconfig)); + + g_object_unref (autoconfig); + + return EXIT_SUCCESS; +} |