/* * 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 * */ #include "e-mail-config-window.h" #include #include #include "e-util/e-util.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 }; enum { CHANGES_COMMITTED, LAST_SIGNAL }; /* Forward Declarations */ static void e_mail_config_window_alert_sink_init (EAlertSinkInterface *interface); static guint signals[LAST_SIGNAL]; 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), "system:simple-error", error->message, NULL); g_object_unref (window); g_error_free (error); } else { g_signal_emit (window, signals[CHANGES_COMMITTED], 0); 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)); signals[CHANGES_COMMITTED] = g_signal_new ( "changes-committed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (EMailConfigWindowClass, changes_committed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } 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; }