/*
* 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
*
*/
#include "e-mail-config-service-page.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 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;
EMailConfigServiceBackend *backend;
GtkComboBox *type_combo;
const gchar *backend_name;
priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page);
type_combo = GTK_COMBO_BOX (priv->type_combo);
backend_name = gtk_combo_box_get_active_id (type_combo);
if (backend_name == NULL)
return FALSE;
backend = e_mail_config_service_page_lookup_backend (
E_MAIL_CONFIG_SERVICE_PAGE (page), backend_name);
return e_mail_config_service_backend_check_complete (backend);
}
static void
mail_config_service_page_commit_changes (EMailConfigPage *page,
GQueue *source_queue)
{
EMailConfigServicePagePrivate *priv;
EMailConfigServiceBackend *backend;
GtkComboBox *type_combo;
const gchar *backend_name;
priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page);
type_combo = GTK_COMBO_BOX (priv->type_combo);
backend_name = gtk_combo_box_get_active_id (type_combo);
g_return_if_fail (backend_name != NULL);
backend = e_mail_config_service_page_lookup_backend (
E_MAIL_CONFIG_SERVICE_PAGE (page), backend_name);
e_mail_config_service_backend_commit_changes (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);
}