[evolution/account-mgmt: 7/54] Adapt libeutil to the new ESource API.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/account-mgmt: 7/54] Adapt libeutil to the new ESource API.
- Date: Tue, 24 Apr 2012 23:45:28 +0000 (UTC)
commit 6d1d256e75d95f1b77eeca9b28af82145318bde9
Author: Matthew Barnes <mbarnes redhat com>
Date: Tue Dec 7 15:30:15 2010 -0600
Adapt libeutil to the new ESource API.
e-util/Makefile.am | 6 +-
e-util/e-async-utils.c | 149 ++++
.../e-account-utils.h => e-util/e-async-utils.h | 30 +-
e-util/e-plugin-util.c | 497 -------------
e-util/e-plugin-util.h | 45 --
e-util/e-source-util.c | 187 +++++
e-util/e-source-util.h | 42 ++
e-util/e-util.c | 46 +-
e-util/e-util.h | 10 +-
libemail-utils/e-account-utils.c | 252 -------
libemail-utils/e-signature-list.c | 501 -------------
libemail-utils/e-signature-list.h | 91 ---
libemail-utils/e-signature-utils.c | 336 ---------
libemail-utils/e-signature-utils.h | 40 -
libemail-utils/e-signature.c | 749 --------------------
libemail-utils/e-signature.h | 90 ---
widgets/misc/Makefile.am | 8 +-
widgets/misc/e-account-combo-box.c | 514 --------------
widgets/misc/e-account-combo-box.h | 85 ---
widgets/misc/e-mail-account-manager.c | 384 ++++++++++
widgets/misc/e-mail-account-manager.h | 77 ++
widgets/misc/e-mail-account-tree-view.c | 575 +++++++++++++++
widgets/misc/e-mail-account-tree-view.h | 83 +++
widgets/misc/e-mail-identity-combo-box.c | 374 ++++++++++
widgets/misc/e-mail-identity-combo-box.h | 76 ++
widgets/misc/test-mail-accounts.c | 61 ++
26 files changed, 2047 insertions(+), 3261 deletions(-)
---
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index 63fce88..9601970 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -19,6 +19,7 @@ privsolib_LTLIBRARIES = libeutil.la
eutilinclude_HEADERS = \
e-activity.h \
+ e-async-utils.h \
e-bit-array.h \
e-categories-config.h \
e-charset.h \
@@ -38,10 +39,10 @@ eutilinclude_HEADERS = \
e-print.h \
e-plugin.h \
e-plugin-ui.h \
- e-plugin-util.h \
e-selection.h \
e-sorter.h \
e-sorter-array.h \
+ e-source-util.h \
e-stock-request.h \
e-text-event-processor-emacs-like.h \
e-text-event-processor-types.h \
@@ -84,6 +85,7 @@ libeutil_la_CPPFLAGS = \
libeutil_la_SOURCES = \
$(eutilinclude_HEADERS) \
e-activity.c \
+ e-async-utils.c \
e-bit-array.c \
e-categories-config.c \
e-charset.c \
@@ -102,11 +104,11 @@ libeutil_la_SOURCES = \
e-poolv.c \
e-plugin.c \
e-plugin-ui.c \
- e-plugin-util.c \
e-print.c \
e-selection.c \
e-sorter.c \
e-sorter-array.c \
+ e-source-util.c \
e-stock-request.c \
e-text-event-processor-emacs-like.c \
e-text-event-processor.c \
diff --git a/e-util/e-async-utils.c b/e-util/e-async-utils.c
new file mode 100644
index 0000000..acc8443
--- /dev/null
+++ b/e-util/e-async-utils.c
@@ -0,0 +1,149 @@
+/*
+ * e-async-utils.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/**
+ * SECTION: e-async-utils
+ * @short_description: utilities for running asynchronous methods
+ * @include: e-util/e-async-utils.h
+ *
+ * #EAsyncClosure provides a simple way to run an asynchronous function
+ * synchronously without blocking a running #GMainLoop.
+ *
+ * 1) Create an #EAsyncClosure with e_async_closure_new().
+ *
+ * 2) Call the asynchronous function passing e_async_closure_callback() as
+ * the #GAsyncReadyCallback argument and the #EAsyncClosure as the data
+ * argument.
+ *
+ * 3) Call e_async_closure_wait() and collect the #GAsyncResult.
+ *
+ * 4) Call the corresponding asynchronous "finish" function, passing the
+ * #GAsyncResult returned by e_async_closure_wait().
+ *
+ * 5) If needed, repeat steps 2-4 for additional asynchronous functions
+ * using the same #EAsyncClosure.
+ *
+ * 6) Finally, free the #EAsyncClosure with e_async_closure_free().
+ **/
+
+#include "e-async-utils.h"
+
+struct _EAsyncClosure {
+ GMainLoop *loop;
+ GMainContext *context;
+ GAsyncResult *result;
+};
+
+/**
+ * e_async_closure_new:
+ *
+ * Creates a new #EAsyncClosure for use with asynchronous functions.
+ *
+ * Returns: a new #EAsyncClosure
+ **/
+EAsyncClosure *
+e_async_closure_new (void)
+{
+ EAsyncClosure *closure;
+
+ closure = g_slice_new0 (EAsyncClosure);
+ closure->context = g_main_context_new ();
+ closure->loop = g_main_loop_new (closure->context, FALSE);
+
+ g_main_context_push_thread_default (closure->context);
+
+ return closure;
+}
+
+/**
+ * e_async_closure_wait:
+ * @closure: an #EAsyncClosure
+ *
+ * Call this function immediately after starting an asynchronous operation.
+ * The function waits for the asynchronous operation to complete and returns
+ * its #GAsyncResult to be passed to the operation's "finish" function.
+ *
+ * This function can be called repeatedly on the same #EAsyncClosure to
+ * easily string together multiple asynchronous operations.
+ *
+ * Returns: a #GAsyncResult
+ **/
+GAsyncResult *
+e_async_closure_wait (EAsyncClosure *closure)
+{
+ g_return_val_if_fail (closure != NULL, NULL);
+
+ g_main_loop_run (closure->loop);
+
+ return closure->result;
+}
+
+/**
+ * e_async_closure_free:
+ * @closure: an #EAsyncClosure
+ *
+ * Frees the @closure and the resources it holds.
+ **/
+void
+e_async_closure_free (EAsyncClosure *closure)
+{
+ g_return_if_fail (closure != NULL);
+
+ g_main_context_pop_thread_default (closure->context);
+
+ g_main_loop_unref (closure->loop);
+ g_main_context_unref (closure->context);
+
+ if (closure->result != NULL)
+ g_object_unref (closure->result);
+
+ g_slice_free (EAsyncClosure, closure);
+}
+
+/**
+ * e_async_closure_callback:
+ * @object: a #GObject
+ * @result: a #GAsyncResult
+ * @closure: an #EAsyncClosure
+ *
+ * Pass this function as the #GAsyncReadyCallback argument of an asynchronous
+ * function, and the #EAsyncClosure as the data argument.
+ *
+ * This causes e_async_closure_wait() to terminate and return @result.
+ **/
+void
+e_async_closure_callback (GObject *object,
+ GAsyncResult *result,
+ gpointer closure)
+{
+ EAsyncClosure *real_closure;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_return_if_fail (closure != NULL);
+
+ real_closure = closure;
+
+ /* Replace any previous result. */
+ if (real_closure->result != NULL)
+ g_object_unref (real_closure->result);
+ real_closure->result = g_object_ref (result);
+
+ g_main_loop_quit (real_closure->loop);
+}
+
diff --git a/libemail-utils/e-account-utils.h b/e-util/e-async-utils.h
similarity index 54%
rename from libemail-utils/e-account-utils.h
rename to e-util/e-async-utils.h
index d7dbd28..002b266 100644
--- a/libemail-utils/e-account-utils.h
+++ b/e-util/e-async-utils.h
@@ -1,4 +1,6 @@
/*
+ * e-async-utils.h
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -12,26 +14,26 @@
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*/
-#ifndef E_ACCOUNT_UTILS_H
-#define E_ACCOUNT_UTILS_H
+#ifndef E_ASYNC_UTILS_H
+#define E_ASYNC_UTILS_H
-#include <camel/camel.h>
-#include <libedataserver/e-account.h>
-#include <libedataserver/e-account-list.h>
+#include <gio/gio.h>
G_BEGIN_DECLS
-EAccountList * e_get_account_list (void);
-EAccount * e_get_default_account (void);
-void e_set_default_account (EAccount *account);
-EAccount * e_get_account_by_name (const gchar *name);
-EAccount * e_get_account_by_uid (const gchar *uid);
-EAccount * e_get_any_enabled_account (void);
-EAccount * e_get_default_transport (void);
+typedef struct _EAsyncClosure EAsyncClosure;
+
+EAsyncClosure * e_async_closure_new (void);
+GAsyncResult * e_async_closure_wait (EAsyncClosure *closure);
+void e_async_closure_free (EAsyncClosure *closure);
+
+/* Use as a GAsyncReadyCallback. */
+void e_async_closure_callback (GObject *object,
+ GAsyncResult *result,
+ gpointer closure);
G_END_DECLS
-#endif /* E_ACCOUNT_UTILS_H */
+#endif /* E_ASYNC_UTILS_H */
diff --git a/e-util/e-source-util.c b/e-util/e-source-util.c
new file mode 100644
index 0000000..61b7897
--- /dev/null
+++ b/e-util/e-source-util.c
@@ -0,0 +1,187 @@
+/*
+ * e-source-util.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-util.h"
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _AsyncContext {
+ EActivity *activity;
+ ESource *source;
+};
+
+static void
+async_context_free (AsyncContext *context)
+{
+ if (context->activity != NULL)
+ g_object_unref (context->activity);
+
+ if (context->source != NULL)
+ g_object_unref (context->source);
+
+ g_slice_free (AsyncContext, context);
+}
+
+static void
+source_util_remove_cb (ESource *source,
+ GAsyncResult *result,
+ AsyncContext *context)
+{
+ EActivity *activity;
+ EAlertSink *alert_sink;
+ GError *error = NULL;
+
+ activity = context->activity;
+ alert_sink = e_activity_get_alert_sink (activity);
+
+ e_source_remove_finish (source, result, &error);
+
+ if (e_activity_handle_cancellation (activity, error)) {
+ g_error_free (error);
+
+ } else if (error != NULL) {
+ e_alert_submit (
+ alert_sink,
+ "source:remove-source-fail",
+ e_source_get_display_name (context->source),
+ error->message, NULL);
+ g_error_free (error);
+
+ } else {
+ e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
+ }
+
+ async_context_free (context);
+}
+
+/**
+ * e_source_util_remove:
+ * @source: the #ESource to be removed
+ * @alert_sink: an #EAlertSink
+ *
+ * Requests the D-Bus service to delete the key files for @source and all of
+ * its descendants and broadcast their removal to all clients. If an error
+ * occurs, an #EAlert will be posted to @alert_sink.
+ *
+ * This function does not block. The returned #EActivity can either be
+ * ignored or passed to something that can display activity status to the
+ * user, such as e_shell_backend_add_activity().
+ *
+ * Returns: an #EActivity to track the operation
+ **/
+EActivity *
+e_source_util_remove (ESource *source,
+ EAlertSink *alert_sink)
+{
+ AsyncContext *context;
+ GCancellable *cancellable;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+ g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL);
+
+ cancellable = g_cancellable_new ();
+
+ context = g_slice_new0 (AsyncContext);
+ context->activity = e_activity_new ();
+ context->source = g_object_ref (source);
+
+ e_activity_set_alert_sink (context->activity, alert_sink);
+ e_activity_set_cancellable (context->activity, cancellable);
+
+ e_source_remove (
+ source, cancellable, (GAsyncReadyCallback)
+ source_util_remove_cb, context);
+
+ g_object_unref (cancellable);
+
+ return context->activity;
+}
+
+static void
+source_util_write_cb (ESource *source,
+ GAsyncResult *result,
+ AsyncContext *context)
+{
+ EActivity *activity;
+ EAlertSink *alert_sink;
+ GError *error = NULL;
+
+ activity = context->activity;
+ alert_sink = e_activity_get_alert_sink (activity);
+
+ e_source_write_finish (source, result, &error);
+
+ if (e_activity_handle_cancellation (activity, error)) {
+ g_error_free (error);
+
+ } else if (error != NULL) {
+ e_alert_submit (
+ alert_sink,
+ "source:submit-data-fail",
+ error->message, NULL);
+ g_error_free (error);
+
+ } else {
+ e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
+ }
+
+ async_context_free (context);
+}
+
+/**
+ * e_source_util_write:
+ * @source: an #ESource
+ * @alert_sink: an #EAlertSink
+ *
+ * Submits the current contents of @source to the D-Bus service to be
+ * written to disk and broadcast to other clients. If an error occurs,
+ * an #EAlert will be posted to @alert_sink.
+ *
+ * This function does not block. The returned #EActivity can either be
+ * ignored or passed to something that can display activity status to the
+ * user, such as e_shell_backend_add_activity().
+ *
+ * Returns: an #EActivity to track the operation
+ **/
+EActivity *
+e_source_util_write (ESource *source,
+ EAlertSink *alert_sink)
+{
+ AsyncContext *context;
+ GCancellable *cancellable;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+ g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL);
+
+ cancellable = g_cancellable_new ();
+
+ context = g_slice_new0 (AsyncContext);
+ context->activity = e_activity_new ();
+
+ e_activity_set_alert_sink (context->activity, alert_sink);
+ e_activity_set_cancellable (context->activity, cancellable);
+
+ e_source_write (
+ source, cancellable, (GAsyncReadyCallback)
+ source_util_write_cb, context);
+
+ g_object_unref (cancellable);
+
+ return context->activity;
+}
+
diff --git a/e-util/e-source-util.h b/e-util/e-source-util.h
new file mode 100644
index 0000000..589e91b
--- /dev/null
+++ b/e-util/e-source-util.h
@@ -0,0 +1,42 @@
+/*
+ * e-source-util.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* These functions combine asynchronous ESource and ESourceRegistry methods
+ * with Evolution's EActivity and EAlert facilities to offer an easy-to-use,
+ * "fire-and-forget" API for ESource operations. Use these in situations
+ * where it's sufficient to just display an error message if the operation
+ * fails, and you don't need to operate on the result. */
+
+#ifndef E_SOURCE_UTIL_H
+#define E_SOURCE_UTIL_H
+
+#include <libedataserver/e-source.h>
+
+#include <e-util/e-activity.h>
+#include <libevolution-utils/e-alert-sink.h>
+
+G_BEGIN_DECLS
+
+EActivity * e_source_util_remove (ESource *source,
+ EAlertSink *alert_sink);
+EActivity * e_source_util_write (ESource *source,
+ EAlertSink *alert_sink);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_UTIL_H */
diff --git a/e-util/e-util.c b/e-util/e-util.c
index 7157351..38c1b85 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -53,7 +53,6 @@
#include <camel/camel.h>
#include <libedataserver/e-data-server-util.h>
#include <libedataserver/e-categories.h>
-#include <libedataserver/e-source-list.h>
#include "filter/e-filter-option.h"
@@ -1334,31 +1333,6 @@ e_util_get_searchable_categories (void)
}
/**
- * e_util_set_source_combo_box_list:
- * @source_combo_box: an #ESourceComboBox
- * @source_gconf_path: GConf path with sources to use in an #ESourceList
- *
- * Sets an #ESourceList of a given GConf path to an #ESourceComboBox.
- **/
-void
-e_util_set_source_combo_box_list (GtkWidget *source_combo_box,
- const gchar *source_gconf_path)
-{
- ESourceList *source_list;
- GConfClient *gconf_client;
-
- g_return_if_fail (source_combo_box != NULL);
- g_return_if_fail (source_gconf_path != NULL);
-
- gconf_client = gconf_client_get_default ();
- source_list = e_source_list_new_for_gconf (
- gconf_client, source_gconf_path);
- g_object_set (source_combo_box, "source-list", source_list, NULL);
- g_object_unref (source_list);
- g_object_unref (gconf_client);
-}
-
-/**
* e_binding_transform_color_to_string:
* @binding: a #GBinding
* @source_value: a #GValue of type #GDK_TYPE_COLOR
@@ -1435,7 +1409,7 @@ e_binding_transform_string_to_color (GBinding *binding,
* @binding: a #GBinding
* @source_value: a #GValue of type #E_TYPE_SOURCE
* @target_value: a #GValue of type #G_TYPE_STRING
- * @source_list: an #ESourceList
+ * @registry: an #ESourceRegistry
*
* Transforms an #ESource object to its UID string.
*
@@ -1445,14 +1419,14 @@ gboolean
e_binding_transform_source_to_uid (GBinding *binding,
const GValue *source_value,
GValue *target_value,
- ESourceList *source_list)
+ ESourceRegistry *registry)
{
ESource *source;
const gchar *string;
gboolean success = FALSE;
g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
- g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
source = g_value_get_object (source_value);
if (E_IS_SOURCE (source)) {
@@ -1469,34 +1443,34 @@ e_binding_transform_source_to_uid (GBinding *binding,
* @binding: a #GBinding
* @source_value: a #GValue of type #G_TYPE_STRING
* @target_value: a #GValue of type #E_TYPE_SOURCe
- * @source_list: an #ESourceList
+ * @registry: an #ESourceRegistry
*
* Transforms an #ESource UID string to the corresponding #ESource object
- * in @source_list.
+ * in @registry.
*
- * Returns: %TRUE if @source_list had an #ESource object with a matching
+ * Returns: %TRUE if @registry had an #ESource object with a matching
* UID string
**/
gboolean
e_binding_transform_uid_to_source (GBinding *binding,
const GValue *source_value,
GValue *target_value,
- ESourceList *source_list)
+ ESourceRegistry *registry)
{
ESource *source;
const gchar *string;
gboolean success = FALSE;
g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
- g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
string = g_value_get_string (source_value);
if (string == NULL || *string == '\0')
return FALSE;
- source = e_source_list_peek_source_by_uid (source_list, string);
+ source = e_source_registry_ref_source (registry, string);
if (source != NULL) {
- g_value_set_object (target_value, source);
+ g_value_take_object (target_value, source);
success = TRUE;
}
diff --git a/e-util/e-util.h b/e-util/e-util.h
index bd9ad2d..af22324 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -32,7 +32,7 @@
#include <e-util/e-marshal.h>
#include <e-util/e-util-enums.h>
-#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-source-registry.h>
/* e_get_user_data_dir() used to live here, so #include its new home
* for backward-compatibility (not that we really care about that). */
@@ -131,10 +131,6 @@ GSList * e_util_get_category_filter_options
(void);
GList * e_util_get_searchable_categories (void);
-void e_util_set_source_combo_box_list
- (GtkWidget *source_combo_box,
- const gchar *source_gconf_path);
-
/* Useful GBinding transform functions */
gboolean e_binding_transform_color_to_string
(GBinding *binding,
@@ -150,12 +146,12 @@ gboolean e_binding_transform_source_to_uid
(GBinding *binding,
const GValue *source_value,
GValue *target_value,
- ESourceList *source_list);
+ ESourceRegistry *registry);
gboolean e_binding_transform_uid_to_source
(GBinding *binding,
const GValue *source_value,
GValue *target_value,
- ESourceList *source_list);
+ ESourceRegistry *registry);
G_END_DECLS
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 411dcb3..bd0bea5 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -5,7 +5,6 @@ widgetsincludedir = $(privincludedir)/misc
ui_DATA = e-send-options.ui
widgetsinclude_HEADERS = \
- e-account-combo-box.h \
e-action-combo-box.h \
e-activity-bar.h \
e-activity-proxy.h \
@@ -38,6 +37,9 @@ widgetsinclude_HEADERS = \
e-image-chooser.h \
e-import-assistant.h \
e-interval-chooser.h \
+ e-mail-account-manager.h \
+ e-mail-account-tree-view.h \
+ e-mail-identity-combo-box.h \
e-map.h \
e-menu-tool-action.h \
e-menu-tool-button.h \
@@ -92,7 +94,6 @@ libemiscwidgets_la_CPPFLAGS = \
libemiscwidgets_la_SOURCES = \
$(widgetsinclude_HEADERS) \
- e-account-combo-box.c \
e-action-combo-box.c \
e-activity-bar.c \
e-activity-proxy.c \
@@ -125,6 +126,9 @@ libemiscwidgets_la_SOURCES = \
e-image-chooser.c \
e-import-assistant.c \
e-interval-chooser.c \
+ e-mail-account-manager.c \
+ e-mail-account-tree-view.c \
+ e-mail-identity-combo-box.c \
e-map.c \
e-menu-tool-action.c \
e-menu-tool-button.c \
diff --git a/widgets/misc/e-mail-account-manager.c b/widgets/misc/e-mail-account-manager.c
new file mode 100644
index 0000000..fd5e999
--- /dev/null
+++ b/widgets/misc/e-mail-account-manager.c
@@ -0,0 +1,384 @@
+/*
+ * e-mail-account-manager.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-account-manager.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "e-mail-account-tree-view.h"
+
+#define E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerPrivate))
+
+struct _EMailAccountManagerPrivate {
+ ESourceRegistry *registry;
+
+ GtkWidget *tree_view; /* not referenced */
+ GtkWidget *add_button; /* not referenced */
+ GtkWidget *edit_button; /* not referenced */
+ GtkWidget *delete_button; /* not referenced */
+ GtkWidget *default_button; /* not referenced */
+};
+
+enum {
+ PROP_0,
+ PROP_REGISTRY
+};
+
+enum {
+ ADD_ACCOUNT,
+ EDIT_ACCOUNT,
+ DELETE_ACCOUNT,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (
+ EMailAccountManager,
+ e_mail_account_manager,
+ GTK_TYPE_TABLE)
+
+static gboolean
+mail_account_manager_key_press_event_cb (EMailAccountManager *manager,
+ GdkEventKey *event)
+{
+ if (event->keyval == GDK_KEY_Delete) {
+ e_mail_account_manager_delete_account (manager);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+mail_account_manager_selection_changed_cb (EMailAccountManager *manager,
+ GtkTreeSelection *selection)
+{
+ EMailAccountTreeView *tree_view;
+ ESourceRegistry *registry;
+ ESource *default_source;
+ ESource *source;
+ GtkWidget *add_button;
+ GtkWidget *edit_button;
+ GtkWidget *delete_button;
+ GtkWidget *default_button;
+ gboolean sensitive;
+
+ add_button = manager->priv->add_button;
+ edit_button = manager->priv->edit_button;
+ delete_button = manager->priv->delete_button;
+ default_button = manager->priv->default_button;
+
+ registry = e_mail_account_manager_get_registry (manager);
+ tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view);
+
+ source = e_mail_account_tree_view_get_selected_source (tree_view);
+ default_source = e_source_registry_get_default_mail_account (registry);
+
+ if (source == NULL)
+ gtk_widget_grab_focus (add_button);
+
+ sensitive = (source != NULL);
+ gtk_widget_set_sensitive (edit_button, sensitive);
+
+ sensitive = (source != NULL);
+ gtk_widget_set_sensitive (delete_button, sensitive);
+
+ sensitive = (source != NULL && source != default_source);
+ gtk_widget_set_sensitive (default_button, sensitive);
+}
+
+static void
+mail_account_manager_set_registry (EMailAccountManager *manager,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (manager->priv->registry == NULL);
+
+ manager->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_account_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ mail_account_manager_set_registry (
+ E_MAIL_ACCOUNT_MANAGER (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_account_manager_get_registry (
+ E_MAIL_ACCOUNT_MANAGER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_manager_dispose (GObject *object)
+{
+ EMailAccountManagerPrivate *priv;
+
+ priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_account_manager_parent_class)->dispose (object);
+}
+
+static void
+mail_account_manager_constructed (GObject *object)
+{
+ EMailAccountManager *manager;
+ ESourceRegistry *registry;
+ GtkTreeSelection *selection;
+ GtkWidget *container;
+ GtkWidget *widget;
+
+ manager = E_MAIL_ACCOUNT_MANAGER (object);
+ registry = e_mail_account_manager_get_registry (manager);
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_account_manager_parent_class)->
+ constructed (object);
+
+ gtk_table_resize (GTK_TABLE (manager), 1, 2);
+ gtk_table_set_col_spacings (GTK_TABLE (manager), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (manager), 12);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_table_attach (
+ GTK_TABLE (container), widget, 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_mail_account_tree_view_new (registry);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ manager->priv->tree_view = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "key-press-event",
+ G_CALLBACK (mail_account_manager_key_press_event_cb),
+ manager);
+
+ g_signal_connect_swapped (
+ widget, "row-activated",
+ G_CALLBACK (e_mail_account_manager_edit_account),
+ manager);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+ g_signal_connect_swapped (
+ selection, "changed",
+ G_CALLBACK (mail_account_manager_selection_changed_cb),
+ manager);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_vbutton_box_new ();
+ gtk_button_box_set_layout (
+ GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
+ gtk_box_set_spacing (GTK_BOX (widget), 6);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 0, 2, 0, GTK_FILL, 0, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_ADD);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->add_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_account_manager_add_account), manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_EDIT);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->edit_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_account_manager_edit_account), manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->delete_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_account_manager_delete_account), manager);
+
+ widget = gtk_button_new_with_mnemonic (_("De_fault"));
+ gtk_button_set_image (
+ GTK_BUTTON (widget),
+ gtk_image_new_from_icon_name (
+ "emblem-default", GTK_ICON_SIZE_BUTTON));
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->default_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_account_tree_view_enable_selected),
+ manager->priv->tree_view);
+}
+
+static void
+e_mail_account_manager_class_init (EMailAccountManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EMailAccountManagerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_account_manager_set_property;
+ object_class->get_property = mail_account_manager_get_property;
+ object_class->dispose = mail_account_manager_dispose;
+ object_class->constructed = mail_account_manager_constructed;
+
+ /* XXX If we moved the account editor to /widgets/misc we
+ * could handle adding and editing accounts directly. */
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ NULL,
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ signals[ADD_ACCOUNT] = g_signal_new (
+ "add-account",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMailAccountManagerClass, add_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[EDIT_ACCOUNT] = g_signal_new (
+ "edit-account",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMailAccountManagerClass, edit_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[DELETE_ACCOUNT] = g_signal_new (
+ "delete-account",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMailAccountManagerClass, delete_account),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+e_mail_account_manager_init (EMailAccountManager *manager)
+{
+ manager->priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (manager);
+}
+
+GtkWidget *
+e_mail_account_manager_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_ACCOUNT_MANAGER,
+ "registry", registry, NULL);
+}
+
+void
+e_mail_account_manager_add_account (EMailAccountManager *manager)
+{
+ g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager));
+
+ g_signal_emit (manager, signals[ADD_ACCOUNT], 0);
+}
+
+void
+e_mail_account_manager_edit_account (EMailAccountManager *manager)
+{
+ g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager));
+
+ g_signal_emit (manager, signals[EDIT_ACCOUNT], 0);
+}
+
+void
+e_mail_account_manager_delete_account (EMailAccountManager *manager)
+{
+ g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager));
+
+ g_signal_emit (manager, signals[DELETE_ACCOUNT], 0);
+}
+
+ESourceRegistry *
+e_mail_account_manager_get_registry (EMailAccountManager *manager)
+{
+ g_return_val_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager), NULL);
+
+ return manager->priv->registry;
+}
diff --git a/widgets/misc/e-mail-account-manager.h b/widgets/misc/e-mail-account-manager.h
new file mode 100644
index 0000000..4afbe70
--- /dev/null
+++ b/widgets/misc/e-mail-account-manager.h
@@ -0,0 +1,77 @@
+/*
+ * e-mail-account-manager.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_ACCOUNT_MANAGER_H
+#define E_MAIL_ACCOUNT_MANAGER_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_ACCOUNT_MANAGER \
+ (e_mail_account_manager_get_type ())
+#define E_MAIL_ACCOUNT_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManager))
+#define E_MAIL_ACCOUNT_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass))
+#define E_IS_MAIL_ACCOUNT_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER))
+#define E_IS_MAIL_ACCOUNT_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_INSTANCE_CLASS \
+ ((cls), E_TYPE_MAIL_ACCOUNT_MANAGER))
+#define E_MAIL_ACCOUNT_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailAccountManager EMailAccountManager;
+typedef struct _EMailAccountManagerClass EMailAccountManagerClass;
+typedef struct _EMailAccountManagerPrivate EMailAccountManagerPrivate;
+
+struct _EMailAccountManager {
+ GtkTable parent;
+ EMailAccountManagerPrivate *priv;
+};
+
+struct _EMailAccountManagerClass {
+ GtkTableClass parent_class;
+
+ void (*add_account) (EMailAccountManager *manager);
+ void (*edit_account) (EMailAccountManager *manager);
+ void (*delete_account) (EMailAccountManager *manager);
+};
+
+GType e_mail_account_manager_get_type (void) G_GNUC_CONST;
+GtkWidget * e_mail_account_manager_new (ESourceRegistry *registry);
+void e_mail_account_manager_add_account
+ (EMailAccountManager *manager);
+void e_mail_account_manager_edit_account
+ (EMailAccountManager *manager);
+void e_mail_account_manager_delete_account
+ (EMailAccountManager *manager);
+ESourceRegistry *
+ e_mail_account_manager_get_registry
+ (EMailAccountManager *manager);
+
+G_END_DECLS
+
+#endif /* E_MAIL_ACCOUNT_MANAGER_H */
diff --git a/widgets/misc/e-mail-account-tree-view.c b/widgets/misc/e-mail-account-tree-view.c
new file mode 100644
index 0000000..45d6a0d
--- /dev/null
+++ b/widgets/misc/e-mail-account-tree-view.c
@@ -0,0 +1,575 @@
+/*
+ * e-mail-account-tree-view.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-account-tree-view.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source-mail-account.h>
+
+#define E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewPrivate))
+
+#define SOURCE_IS_MAIL_ACCOUNT(source) \
+ (e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_ACCOUNT))
+
+struct _EMailAccountTreeViewPrivate {
+ ESourceRegistry *registry;
+ guint refresh_idle_id;
+};
+
+enum {
+ PROP_0,
+ PROP_REGISTRY
+};
+
+enum {
+ ENABLE_SELECTED,
+ DISABLE_SELECTED,
+ LAST_SIGNAL
+};
+
+enum {
+ COLUMN_DISPLAY_NAME,
+ COLUMN_BACKEND_NAME,
+ COLUMN_DEFAULT,
+ COLUMN_ENABLED,
+ COLUMN_UID
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (
+ EMailAccountTreeView,
+ e_mail_account_tree_view,
+ GTK_TYPE_TREE_VIEW)
+
+static gboolean
+mail_account_tree_view_refresh_idle_cb (EMailAccountTreeView *tree_view)
+{
+ /* The refresh function will clear the idle ID. */
+ e_mail_account_tree_view_refresh (tree_view);
+
+ return FALSE;
+}
+
+static void
+mail_account_tree_view_registry_changed (ESourceRegistry *registry,
+ ESource *source,
+ EMailAccountTreeView *tree_view)
+{
+ /* If the ESource in question has a "Mail Account" extension,
+ * schedule a refresh of the tree model. Otherwise ignore it.
+ * We use an idle callback to limit how frequently we refresh
+ * the tree model, in case the registry is emitting lots of
+ * signals at once. */
+
+ if (!SOURCE_IS_MAIL_ACCOUNT (source))
+ return;
+
+ if (tree_view->priv->refresh_idle_id > 0)
+ return;
+
+ tree_view->priv->refresh_idle_id = gdk_threads_add_idle (
+ (GSourceFunc) mail_account_tree_view_refresh_idle_cb,
+ tree_view);
+}
+
+static void
+mail_account_tree_view_enabled_toggled_cb (GtkCellRendererToggle *cell_renderer,
+ const gchar *path_string,
+ EMailAccountTreeView *tree_view)
+{
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+
+ /* Chain the selection first so we enable or disable the
+ * correct account. */
+ path = gtk_tree_path_new_from_string (path_string);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+
+ if (gtk_cell_renderer_toggle_get_active (cell_renderer))
+ e_mail_account_tree_view_disable_selected (tree_view);
+ else
+ e_mail_account_tree_view_enable_selected (tree_view);
+}
+
+static void
+mail_account_tree_view_set_registry (EMailAccountTreeView *tree_view,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (tree_view->priv->registry == NULL);
+
+ tree_view->priv->registry = g_object_ref (registry);
+
+ g_signal_connect (
+ registry, "source-added",
+ G_CALLBACK (mail_account_tree_view_registry_changed),
+ tree_view);
+
+ g_signal_connect (
+ registry, "source-changed",
+ G_CALLBACK (mail_account_tree_view_registry_changed),
+ tree_view);
+
+ g_signal_connect (
+ registry, "source-removed",
+ G_CALLBACK (mail_account_tree_view_registry_changed),
+ tree_view);
+}
+
+static void
+mail_account_tree_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ mail_account_tree_view_set_registry (
+ E_MAIL_ACCOUNT_TREE_VIEW (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_tree_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_account_tree_view_get_registry (
+ E_MAIL_ACCOUNT_TREE_VIEW (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_tree_view_dispose (GObject *object)
+{
+ EMailAccountTreeViewPrivate *priv;
+
+ priv = E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->registry, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ if (priv->refresh_idle_id > 0) {
+ g_source_remove (priv->refresh_idle_id);
+ priv->refresh_idle_id = 0;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_account_tree_view_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_account_tree_view_constructed (GObject *object)
+{
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell_renderer;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_account_tree_view_parent_class)->
+ constructed (object);
+
+ tree_view = GTK_TREE_VIEW (object);
+ gtk_tree_view_set_headers_visible (tree_view, TRUE);
+
+ /* Column: Enabled */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_column_set_title (column, _("Enabled"));
+
+ cell_renderer = gtk_cell_renderer_toggle_new ();
+ gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+
+ g_signal_connect (
+ cell_renderer, "toggled",
+ G_CALLBACK (mail_account_tree_view_enabled_toggled_cb),
+ tree_view);
+
+ gtk_tree_view_column_add_attribute (
+ column, cell_renderer, "active", COLUMN_ENABLED);
+
+ gtk_tree_view_append_column (tree_view, column);
+
+ /* Column: Account Name */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_column_set_title (column, _("Account Name"));
+
+ cell_renderer = gtk_cell_renderer_text_new ();
+ g_object_set (cell_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+
+ gtk_tree_view_column_add_attribute (
+ column, cell_renderer, "text", COLUMN_DISPLAY_NAME);
+
+ cell_renderer = gtk_cell_renderer_text_new ();
+ g_object_set (cell_renderer, "text", _("Default"), NULL);
+ gtk_tree_view_column_pack_end (column, cell_renderer, FALSE);
+
+ gtk_tree_view_column_add_attribute (
+ column, cell_renderer, "visible", COLUMN_DISPLAY_NAME);
+
+ cell_renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (
+ cell_renderer, "icon-name", "emblem-default",
+ "stock-size", GTK_ICON_SIZE_MENU, NULL);
+ gtk_tree_view_column_pack_end (column, cell_renderer, FALSE);
+
+ gtk_tree_view_column_add_attribute (
+ column, cell_renderer, "visible", COLUMN_DISPLAY_NAME);
+
+ gtk_tree_view_append_column (tree_view, column);
+
+ /* Column: Type */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_column_set_title (column, _("Type"));
+
+ cell_renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+
+ gtk_tree_view_column_add_attribute (
+ column, cell_renderer, "text", COLUMN_BACKEND_NAME);
+
+ gtk_tree_view_append_column (tree_view, column);
+
+ e_mail_account_tree_view_refresh (E_MAIL_ACCOUNT_TREE_VIEW (object));
+}
+
+static void
+mail_account_tree_view_enable_selected (EMailAccountTreeView *tree_view)
+{
+ ESource *source;
+ ESourceMailAccount *mail_account;
+ const gchar *extension_name;
+ GError *error = NULL;
+
+ source = e_mail_account_tree_view_get_selected_source (tree_view);
+
+ if (source == NULL)
+ return;
+
+ /* The source should already be a mail account. */
+ g_return_if_fail (SOURCE_IS_MAIL_ACCOUNT (source));
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+ mail_account = e_source_get_extension (source, extension_name);
+
+ /* Avoid unnecessary signal emissions and disk writes. */
+ if (e_source_mail_account_get_enabled (mail_account))
+ return;
+
+ e_source_mail_account_set_enabled (mail_account, TRUE);
+
+ if (!e_source_sync (source, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+mail_account_tree_view_disable_selected (EMailAccountTreeView *tree_view)
+{
+ ESource *source;
+ ESourceMailAccount *mail_account;
+ const gchar *extension_name;
+ GError *error = NULL;
+
+ source = e_mail_account_tree_view_get_selected_source (tree_view);
+
+ if (source == NULL)
+ return;
+
+ /* The source should already be a mail account. */
+ g_return_if_fail (SOURCE_IS_MAIL_ACCOUNT (source));
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+ mail_account = e_source_get_extension (source, extension_name);
+
+ /* Avoid unnecessary signal emissions and disk writes. */
+ if (!e_source_mail_account_get_enabled (mail_account))
+ return;
+
+ e_source_mail_account_set_enabled (mail_account, FALSE);
+
+ if (!e_source_sync (source, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+e_mail_account_tree_view_class_init (EMailAccountTreeViewClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EMailAccountTreeViewPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_account_tree_view_set_property;
+ object_class->get_property = mail_account_tree_view_get_property;
+ object_class->dispose = mail_account_tree_view_dispose;
+ object_class->constructed = mail_account_tree_view_constructed;
+
+ class->enable_selected = mail_account_tree_view_enable_selected;
+ class->disable_selected = mail_account_tree_view_disable_selected;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ NULL,
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ signals[ENABLE_SELECTED] = g_signal_new (
+ "enable-selected",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMailAccountTreeViewClass, enable_selected),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[DISABLE_SELECTED] = g_signal_new (
+ "disable-selected",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMailAccountTreeViewClass, disable_selected),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+e_mail_account_tree_view_init (EMailAccountTreeView *tree_view)
+{
+ tree_view->priv = E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE (tree_view);
+}
+
+GtkWidget *
+e_mail_account_tree_view_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_ACCOUNT_TREE_VIEW,
+ "registry", registry, NULL);
+}
+
+void
+e_mail_account_tree_view_refresh (EMailAccountTreeView *tree_view)
+{
+ ESourceRegistry *registry;
+ GtkTreeModel *tree_model;
+ ESource *default_source;
+ ESource *source;
+ GList *list, *link;
+ const gchar *extension_name;
+ gchar *saved_uid = NULL;
+
+ g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view));
+
+ if (tree_view->priv->refresh_idle_id > 0) {
+ g_source_remove (tree_view->priv->refresh_idle_id);
+ tree_view->priv->refresh_idle_id = 0;
+ }
+
+ registry = e_mail_account_tree_view_get_registry (tree_view);
+ tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+
+ source = e_mail_account_tree_view_get_selected_source (tree_view);
+ if (source != NULL)
+ saved_uid = g_strdup (e_source_get_uid (source));
+
+ default_source = e_source_registry_get_default_mail_account (registry);
+
+ gtk_list_store_clear (GTK_LIST_STORE (tree_model));
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+ list = e_source_registry_list_sources (registry, extension_name);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ ESourceMailAccount *mail_account;
+ GtkTreeIter iter;
+ const gchar *backend_name;
+ const gchar *display_name;
+ const gchar *uid;
+ gboolean is_default;
+ gboolean is_enabled;
+
+ source = E_SOURCE (link->data);
+ mail_account = e_source_get_extension (source, extension_name);
+
+ display_name = e_source_get_display_name (source);
+ backend_name = e_source_get_backend_name (source);
+ is_default = e_source_equal (source, default_source);
+ is_enabled = e_source_mail_account_get_enabled (mail_account);
+ uid = e_source_get_uid (source);
+
+ gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (tree_model), &iter,
+ COLUMN_DISPLAY_NAME, display_name,
+ COLUMN_BACKEND_NAME, backend_name,
+ COLUMN_DEFAULT, is_default,
+ COLUMN_ENABLED, is_enabled,
+ COLUMN_UID, uid, -1);
+ }
+
+ g_list_free (list);
+
+ /* Try and restore the previous selected source,
+ * or else just pick the default mail account. */
+
+ source = NULL;
+
+ if (saved_uid != NULL) {
+ source = e_source_registry_lookup_by_uid (registry, saved_uid);
+ g_free (saved_uid);
+ }
+
+ if (source == NULL)
+ source = default_source;
+
+ if (source != NULL)
+ e_mail_account_tree_view_set_selected_source (
+ tree_view, source);
+}
+
+void
+e_mail_account_tree_view_enable_selected (EMailAccountTreeView *tree_view)
+{
+ g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view));
+
+ g_signal_emit (tree_view, signals[ENABLE_SELECTED], 0);
+}
+
+void
+e_mail_account_tree_view_disable_selected (EMailAccountTreeView *tree_view)
+{
+ g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view));
+
+ g_signal_emit (tree_view, signals[DISABLE_SELECTED], 0);
+}
+
+ESourceRegistry *
+e_mail_account_tree_view_get_registry (EMailAccountTreeView *tree_view)
+{
+ g_return_val_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view), NULL);
+
+ return tree_view->priv->registry;
+}
+
+ESource *
+e_mail_account_tree_view_get_selected_source (EMailAccountTreeView *tree_view)
+{
+ ESourceRegistry *registry;
+ GtkTreeSelection *selection;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ ESource *source;
+ gchar *uid;
+
+ g_return_val_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view), NULL);
+
+ registry = e_mail_account_tree_view_get_registry (tree_view);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ if (!gtk_tree_selection_get_selected (selection, &tree_model, &iter))
+ return NULL;
+
+ gtk_tree_model_get (tree_model, &iter, COLUMN_UID, &uid, -1);
+ source = e_source_registry_lookup_by_uid (registry, uid);
+ g_free (uid);
+
+ return source;
+}
+
+void
+e_mail_account_tree_view_set_selected_source (EMailAccountTreeView *tree_view,
+ ESource *source)
+{
+ ESourceRegistry *registry;
+ GtkTreeSelection *selection;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ gboolean valid;
+
+ g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ /* It is a programming error to pass an ESource that has no
+ * "Mail Account" extension. */
+ g_return_if_fail (SOURCE_IS_MAIL_ACCOUNT (source));
+
+ registry = e_mail_account_tree_view_get_registry (tree_view);
+ tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ valid = gtk_tree_model_get_iter_first (tree_model, &iter);
+
+ while (valid) {
+ ESource *candidate;
+ gchar *uid;
+
+ gtk_tree_model_get (tree_model, &iter, COLUMN_UID, &uid, -1);
+ candidate = e_source_registry_lookup_by_uid (registry, uid);
+ g_free (uid);
+
+ if (candidate != NULL && e_source_equal (source, candidate)) {
+ gtk_tree_selection_select_iter (selection, &iter);
+ break;
+ }
+
+ valid = gtk_tree_model_iter_next (tree_model, &iter);
+ }
+}
diff --git a/widgets/misc/e-mail-account-tree-view.h b/widgets/misc/e-mail-account-tree-view.h
new file mode 100644
index 0000000..4bf9099
--- /dev/null
+++ b/widgets/misc/e-mail-account-tree-view.h
@@ -0,0 +1,83 @@
+/*
+ * e-mail-account-tree-view.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_ACCOUNT_TREE_VIEW_H
+#define E_MAIL_ACCOUNT_TREE_VIEW_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_ACCOUNT_TREE_VIEW \
+ (e_mail_account_tree_view_get_type ())
+#define E_MAIL_ACCOUNT_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeView))
+#define E_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass))
+#define E_IS_MAIL_ACCOUNT_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW))
+#define E_IS_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW))
+#define E_MAIL_ACCOUNT_TREE_VIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailAccountTreeView EMailAccountTreeView;
+typedef struct _EMailAccountTreeViewClass EMailAccountTreeViewClass;
+typedef struct _EMailAccountTreeViewPrivate EMailAccountTreeViewPrivate;
+
+struct _EMailAccountTreeView {
+ GtkTreeView parent;
+ EMailAccountTreeViewPrivate *priv;
+};
+
+struct _EMailAccountTreeViewClass {
+ GtkTreeViewClass parent_class;
+
+ void (*enable_selected) (EMailAccountTreeView *tree_view);
+ void (*disable_selected) (EMailAccountTreeView *tree_view);
+};
+
+GType e_mail_account_tree_view_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_account_tree_view_new
+ (ESourceRegistry *registry);
+void e_mail_account_tree_view_refresh
+ (EMailAccountTreeView *tree_view);
+void e_mail_account_tree_view_enable_selected
+ (EMailAccountTreeView *tree_view);
+void e_mail_account_tree_view_disable_selected
+ (EMailAccountTreeView *tree_view);
+ESourceRegistry *
+ e_mail_account_tree_view_get_registry
+ (EMailAccountTreeView *tree_view);
+ESource * e_mail_account_tree_view_get_selected_source
+ (EMailAccountTreeView *tree_view);
+void e_mail_account_tree_view_set_selected_source
+ (EMailAccountTreeView *tree_view,
+ ESource *source);
+
+G_END_DECLS
+
+#endif /* E_MAIL_ACCOUNT_TREE_VIEW_H */
diff --git a/widgets/misc/e-mail-identity-combo-box.c b/widgets/misc/e-mail-identity-combo-box.c
new file mode 100644
index 0000000..4b83015
--- /dev/null
+++ b/widgets/misc/e-mail-identity-combo-box.c
@@ -0,0 +1,374 @@
+/*
+ * e-mail-identity-combo-box.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-identity-combo-box.h"
+
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-identity.h>
+
+#define E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBoxPrivate))
+
+#define SOURCE_IS_MAIL_IDENTITY(source) \
+ (e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_IDENTITY))
+
+struct _EMailIdentityComboBoxPrivate {
+ ESourceRegistry *registry;
+ guint refresh_idle_id;
+};
+
+enum {
+ PROP_0,
+ PROP_REGISTRY
+};
+
+enum {
+ COLUMN_DISPLAY_NAME,
+ COLUMN_UID
+};
+
+G_DEFINE_TYPE (
+ EMailIdentityComboBox,
+ e_mail_identity_combo_box,
+ GTK_TYPE_COMBO_BOX)
+
+static gboolean
+mail_identity_combo_box_refresh_idle_cb (EMailIdentityComboBox *combo_box)
+{
+ /* The refresh function will clear the idle ID. */
+ e_mail_identity_combo_box_refresh (combo_box);
+
+ return FALSE;
+}
+
+static void
+mail_identity_combo_box_registry_changed (ESourceRegistry *registry,
+ ESource *source,
+ EMailIdentityComboBox *combo_box)
+{
+ /* If the ESource in question has a "Mail Identity" extension,
+ * schedule a refresh of the tree model. Otherwise ignore it.
+ * We use an idle callback to limit how frequently we refresh
+ * the tree model, in case the registry is emitting lots of
+ * signals at once. */
+
+ if (!SOURCE_IS_MAIL_IDENTITY (source))
+ return;
+
+ if (combo_box->priv->refresh_idle_id > 0)
+ return;
+
+ combo_box->priv->refresh_idle_id = gdk_threads_add_idle (
+ (GSourceFunc) mail_identity_combo_box_refresh_idle_cb,
+ combo_box);
+}
+
+static ESource *
+mail_identity_combo_box_get_default (EMailIdentityComboBox *combo_box)
+{
+ ESource *source;
+ ESourceRegistry *registry;
+ ESourceMailAccount *mail_account;
+ const gchar *extension_name;
+ const gchar *uid;
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+ registry = e_mail_identity_combo_box_get_registry (combo_box);
+ source = e_source_registry_get_default_mail_account (registry);
+
+ if (source == NULL)
+ return NULL;
+
+ if (!e_source_has_extension (source, extension_name))
+ return NULL;
+
+ mail_account = e_source_get_extension (source, extension_name);
+ uid = e_source_mail_account_get_identity (mail_account);
+
+ if (uid == NULL)
+ return NULL;
+
+ return e_source_registry_lookup_by_uid (registry, uid);
+}
+
+static void
+mail_identity_combo_box_set_registry (EMailIdentityComboBox *combo_box,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (combo_box->priv->registry == NULL);
+
+ combo_box->priv->registry = g_object_ref (registry);
+
+ g_signal_connect (
+ registry, "source-added",
+ G_CALLBACK (mail_identity_combo_box_registry_changed),
+ combo_box);
+
+ g_signal_connect (
+ registry, "source-changed",
+ G_CALLBACK (mail_identity_combo_box_registry_changed),
+ combo_box);
+
+ g_signal_connect (
+ registry, "source-removed",
+ G_CALLBACK (mail_identity_combo_box_registry_changed),
+ combo_box);
+}
+
+static void
+mail_identity_combo_box_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ mail_identity_combo_box_set_registry (
+ E_MAIL_IDENTITY_COMBO_BOX (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_identity_combo_box_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_identity_combo_box_get_registry (
+ E_MAIL_IDENTITY_COMBO_BOX (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_identity_combo_box_dispose (GObject *object)
+{
+ EMailIdentityComboBoxPrivate *priv;
+
+ priv = E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->registry, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ if (priv->refresh_idle_id > 0) {
+ g_source_remove (priv->refresh_idle_id);
+ priv->refresh_idle_id = 0;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_identity_combo_box_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_identity_combo_box_constructed (GObject *object)
+{
+ GtkListStore *list_store;
+ GtkComboBox *combo_box;
+ GtkCellLayout *cell_layout;
+ GtkCellRenderer *cell_renderer;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_identity_combo_box_parent_class)->
+ constructed (object);
+
+ combo_box = GTK_COMBO_BOX (object);
+ cell_layout = GTK_CELL_LAYOUT (object);
+
+ list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (list_store));
+ gtk_combo_box_set_id_column (combo_box, COLUMN_UID);
+ g_object_unref (list_store);
+
+ cell_renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (cell_layout, cell_renderer, TRUE);
+ gtk_cell_layout_add_attribute (
+ cell_layout, cell_renderer, "text", COLUMN_DISPLAY_NAME);
+
+ e_mail_identity_combo_box_refresh (E_MAIL_IDENTITY_COMBO_BOX (object));
+}
+
+static void
+e_mail_identity_combo_box_class_init (EMailIdentityComboBoxClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EMailIdentityComboBoxPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_identity_combo_box_set_property;
+ object_class->get_property = mail_identity_combo_box_get_property;
+ object_class->dispose = mail_identity_combo_box_dispose;
+ object_class->constructed = mail_identity_combo_box_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ NULL,
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_identity_combo_box_init (EMailIdentityComboBox *combo_box)
+{
+ combo_box->priv = E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE (combo_box);
+}
+
+GtkWidget *
+e_mail_identity_combo_box_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_IDENTITY_COMBO_BOX,
+ "registry", registry, NULL);
+}
+
+void
+e_mail_identity_combo_box_refresh (EMailIdentityComboBox *combo_box)
+{
+ ESourceRegistry *registry;
+ GtkTreeModel *tree_model;
+ ESource *source;
+ GList *list, *link;
+ const gchar *extension_name;
+ gchar *saved_uid = NULL;
+
+ g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box));
+
+ if (combo_box->priv->refresh_idle_id > 0) {
+ g_source_remove (combo_box->priv->refresh_idle_id);
+ combo_box->priv->refresh_idle_id = 0;
+ }
+
+ registry = e_mail_identity_combo_box_get_registry (combo_box);
+ tree_model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+
+ source = e_mail_identity_combo_box_get_active_source (combo_box);
+ if (source != NULL)
+ saved_uid = g_strdup (e_source_get_uid (source));
+
+ gtk_list_store_clear (GTK_LIST_STORE (tree_model));
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+ list = e_source_registry_list_sources (registry, extension_name);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ GtkTreeIter iter;
+ const gchar *display_name;
+ const gchar *uid;
+
+ source = E_SOURCE (link->data);
+ display_name = e_source_get_display_name (source);
+ uid = e_source_get_uid (source);
+
+ gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (tree_model), &iter,
+ COLUMN_DISPLAY_NAME, display_name,
+ COLUMN_UID, uid, -1);
+ }
+
+ g_list_free (list);
+
+ /* Try and restore the previous selected source, or else pick
+ * the default identity of the default mail account. If even
+ * that fails, just pick the first item. */
+
+ source = NULL;
+
+ if (saved_uid != NULL) {
+ source = e_source_registry_lookup_by_uid (registry, saved_uid);
+ g_free (saved_uid);
+ }
+
+ if (source == NULL)
+ source = mail_identity_combo_box_get_default (combo_box);
+
+ if (source != NULL)
+ e_mail_identity_combo_box_set_active_source (combo_box, source);
+ else
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+}
+
+ESourceRegistry *
+e_mail_identity_combo_box_get_registry (EMailIdentityComboBox *combo_box)
+{
+ g_return_val_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box), NULL);
+
+ return combo_box->priv->registry;
+}
+
+ESource *
+e_mail_identity_combo_box_get_active_source (EMailIdentityComboBox *combo_box)
+{
+ ESourceRegistry *registry;
+ ESource *source = NULL;
+ const gchar *uid;
+
+ g_return_val_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box), NULL);
+
+ registry = e_mail_identity_combo_box_get_registry (combo_box);
+ uid = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
+
+ if (uid != NULL)
+ source = e_source_registry_lookup_by_uid (registry, uid);
+
+ return source;
+}
+
+void
+e_mail_identity_combo_box_set_active_source (EMailIdentityComboBox *combo_box,
+ ESource *active_source)
+{
+ const gchar *uid;
+
+ g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box));
+ g_return_if_fail (E_IS_SOURCE (active_source));
+
+ /* It is a programming error to pass an ESource that has no
+ * "Mail Identity" extension. */
+ g_return_if_fail (SOURCE_IS_MAIL_IDENTITY (active_source));
+
+ uid = e_source_get_uid (active_source);
+ gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), uid);
+}
diff --git a/widgets/misc/e-mail-identity-combo-box.h b/widgets/misc/e-mail-identity-combo-box.h
new file mode 100644
index 0000000..b40957d
--- /dev/null
+++ b/widgets/misc/e-mail-identity-combo-box.h
@@ -0,0 +1,76 @@
+/*
+ * e-mail-identity-combo-box.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_IDENTITY_COMBO_BOX_H
+#define E_MAIL_IDENTITY_COMBO_BOX_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_IDENTITY_COMBO_BOX \
+ (e_mail_identity_combo_box_get_type ())
+#define E_MAIL_IDENTITY_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBox))
+#define E_MAIL_IDENTITY_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBoxClass))
+#define E_IS_MAIL_IDENTITY_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX))
+#define E_IS_MAIL_IDENTITY_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_IDENTITY_COMBO_BOX))
+#define E_MAIL_IDENTITY_COMBO_BOX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailIdentityComboBox EMailIdentityComboBox;
+typedef struct _EMailIdentityComboBoxClass EMailIdentityComboBoxClass;
+typedef struct _EMailIdentityComboBoxPrivate EMailIdentityComboBoxPrivate;
+
+struct _EMailIdentityComboBox {
+ GtkComboBox parent;
+ EMailIdentityComboBoxPrivate *priv;
+};
+
+struct _EMailIdentityComboBoxClass {
+ GtkComboBoxClass parent_class;
+};
+
+GType e_mail_identity_combo_box_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_identity_combo_box_new
+ (ESourceRegistry *registry);
+void e_mail_identity_combo_box_refresh
+ (EMailIdentityComboBox *combo_box);
+ESourceRegistry *
+ e_mail_identity_combo_box_get_registry
+ (EMailIdentityComboBox *combo_box);
+ESource * e_mail_identity_combo_box_get_active_source
+ (EMailIdentityComboBox *combo_box);
+void e_mail_identity_combo_box_set_active_source
+ (EMailIdentityComboBox *combo_box,
+ ESource *active_source);
+
+G_END_DECLS
+
+#endif /* E_MAIL_IDENTITY_COMBO_BOX_H */
diff --git a/widgets/misc/test-mail-accounts.c b/widgets/misc/test-mail-accounts.c
new file mode 100644
index 0000000..92069b4
--- /dev/null
+++ b/widgets/misc/test-mail-accounts.c
@@ -0,0 +1,61 @@
+/*
+ * test-mail-accounts.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <misc/e-mail-account-manager.h>
+#include <misc/e-mail-identity-combo-box.h>
+
+gint
+main (gint argc, gchar **argv)
+{
+ ESourceRegistry *registry;
+ GtkWidget *container;
+ GtkWidget *widget;
+ GtkWidget *window;
+
+ gtk_init (&argc, &argv);
+
+ registry = e_source_registry_get_default ();
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "Mail Sources");
+ gtk_widget_set_default_size (GTK_WINDOW (window), 400, 400);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+ gtk_widget_show (window);
+
+ g_signal_connect (
+ window, "delete-event",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ widget = gtk_vbox_new (FALSE, 12);
+ gtk_container_add (GTK_CONTAINER (window), widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_mail_identity_combo_box_new (registry);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = e_mail_account_manager_new (registry);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ gtk_main ();
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]